diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 136efbd756e..66ba5033562 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -59,6 +59,7 @@ JVM_CFLAGS_INCLUDES += \ -I$(TOPDIR)/src/hotspot/share/precompiled \ -I$(TOPDIR)/src/java.base/share/native/include \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include \ + -I$(TOPDIR)/src/java.management/share/native/include \ -I$(TOPDIR)/src/java.base/share/native/libjimage \ # diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk index 9c621f53410..8cf3b0ed6f3 100644 --- a/make/test/JtregNativeHotspot.gmk +++ b/make/test/JtregNativeHotspot.gmk @@ -79,6 +79,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC += \ $(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare \ $(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart \ $(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/StartPhase/AllowedFunctions \ + $(TOPDIR)/test/hotspot/jtreg/serviceability/dcmd/jvmti/AttachFailed \ # # Add conditional directories here when needed. @@ -110,6 +111,8 @@ ifeq ($(TOOLCHAIN_TYPE), solstudio) BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libAllowedFunctions := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libRedefineDoubleDelete := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libHandshakeTransitionTest := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libHasNoEntryPoint := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libReturnError := -lc endif ifeq ($(OPENJDK_TARGET_OS), linux) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index ab1bcd55817..2a9766f5143 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -985,12 +985,33 @@ public: } void hint(int imm) { - system(0b00, 0b011, 0b0010, imm, 0b000); + system(0b00, 0b011, 0b0010, 0b0000, imm); } void nop() { hint(0); } + + void yield() { + hint(1); + } + + void wfe() { + hint(2); + } + + void wfi() { + hint(3); + } + + void sev() { + hint(4); + } + + void sevl() { + hint(5); + } + // we only provide mrs and msr for the special purpose system // registers where op1 (instr[20:19]) == 11 and, (currently) only // use it for FPSR n.b msr has L (instr[21]) == 0 mrs has L == 1 diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 36fefc866aa..ecd4a8e19f2 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -494,42 +494,6 @@ void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) { } } -// Rather than take a segfault when the polling page is protected, -// explicitly check for a safepoint in progress and if there is one, -// fake a call to the handler as if a segfault had been caught. -void LIR_Assembler::poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo* info) { - __ mov(rscratch1, SafepointSynchronize::address_of_state()); - __ ldrb(rscratch1, Address(rscratch1)); - Label nope, poll; - __ cbz(rscratch1, nope); - __ block_comment("safepoint"); - __ enter(); - __ push(0x3, sp); // r0 & r1 - __ push(0x3ffffffc, sp); // integer registers except lr & sp & r0 & r1 - __ adr(r0, poll); - __ str(r0, Address(rthread, JavaThread::saved_exception_pc_offset())); - __ mov(rscratch1, CAST_FROM_FN_PTR(address, SharedRuntime::get_poll_stub)); - __ blrt(rscratch1, 1, 0, 1); - __ maybe_isb(); - __ pop(0x3ffffffc, sp); // integer registers except lr & sp & r0 & r1 - __ mov(rscratch1, r0); - __ pop(0x3, sp); // r0 & r1 - __ leave(); - __ br(rscratch1); - address polling_page(os::get_polling_page()); - assert(os::is_poll_address(polling_page), "should be"); - unsigned long off; - __ adrp(rscratch1, Address(polling_page, rtype), off); - __ bind(poll); - if (info) - add_debug_info_for_branch(info); // This isn't just debug info: - // it's the oop map - else - __ code_section()->relocate(pc(), rtype); - __ ldrw(zr, Address(rscratch1, off)); - __ bind(nope); -} - void LIR_Assembler::return_op(LIR_Opr result) { assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == r0, "word returns are in r0,"); @@ -549,11 +513,9 @@ int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { address polling_page(os::get_polling_page()); guarantee(info != NULL, "Shouldn't be NULL"); assert(os::is_poll_address(polling_page), "should be"); - unsigned long off; - __ adrp(rscratch1, Address(polling_page, relocInfo::poll_type), off); - assert(off == 0, "must be"); + __ get_polling_page(rscratch1, polling_page, relocInfo::poll_type); add_debug_info_for_branch(info); // This isn't just debug info: - // it's the oop map + // it's the oop map __ read_polling_page(rscratch1, relocInfo::poll_type); return __ offset(); } diff --git a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp index ad6b12de22d..5977764c2d2 100644 --- a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp @@ -51,4 +51,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define SUPPORT_RESERVED_STACK_AREA +#define THREAD_LOCAL_POLL + #endif // CPU_AARCH64_VM_GLOBALDEFINITIONS_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index bf34c157c9e..dfd984e4fb0 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -79,7 +79,7 @@ define_pd_global(bool, CompactStrings, true); // Clear short arrays bigger than one word in an arch-specific way define_pd_global(intx, InitArrayShortSize, BytesPerLong); -define_pd_global(bool, ThreadLocalHandshakes, false); +define_pd_global(bool, ThreadLocalHandshakes, true); #if defined(COMPILER1) || defined(COMPILER2) define_pd_global(intx, InlineSmallCode, 1000); diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index b1b3c5e5273..550bf100764 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -30,12 +30,13 @@ #include "logging/log.hpp" #include "oops/arrayOop.hpp" #include "oops/markOop.hpp" -#include "oops/methodData.hpp" #include "oops/method.hpp" +#include "oops/methodData.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" #include "runtime/basicLock.hpp" #include "runtime/biasedLocking.hpp" +#include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" @@ -438,13 +439,26 @@ void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) { void InterpreterMacroAssembler::dispatch_base(TosState state, address* table, - bool verifyoop) { + bool verifyoop, + bool generate_poll) { if (VerifyActivationFrameSize) { Unimplemented(); } if (verifyoop) { verify_oop(r0, state); } + + Label safepoint; + address* const safepoint_table = Interpreter::safept_table(state); + bool needs_thread_local_poll = generate_poll && + SafepointMechanism::uses_thread_local_poll() && table != safepoint_table; + + if (needs_thread_local_poll) { + NOT_PRODUCT(block_comment("Thread-local Safepoint poll")); + ldr(rscratch2, Address(rthread, Thread::polling_page_offset())); + tbnz(rscratch2, exact_log2(SafepointMechanism::poll_bit()), safepoint); + } + if (table == Interpreter::dispatch_table(state)) { addw(rscratch2, rscratch1, Interpreter::distance_from_dispatch_table(state)); ldr(rscratch2, Address(rdispatch, rscratch2, Address::uxtw(3))); @@ -453,10 +467,17 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, ldr(rscratch2, Address(rscratch2, rscratch1, Address::uxtw(3))); } br(rscratch2); + + if (needs_thread_local_poll) { + bind(safepoint); + lea(rscratch2, ExternalAddress((address)safepoint_table)); + ldr(rscratch2, Address(rscratch2, rscratch1, Address::uxtw(3))); + br(rscratch2); + } } -void InterpreterMacroAssembler::dispatch_only(TosState state) { - dispatch_base(state, Interpreter::dispatch_table(state)); +void InterpreterMacroAssembler::dispatch_only(TosState state, bool generate_poll) { + dispatch_base(state, Interpreter::dispatch_table(state), true, generate_poll); } void InterpreterMacroAssembler::dispatch_only_normal(TosState state) { @@ -468,10 +489,10 @@ void InterpreterMacroAssembler::dispatch_only_noverify(TosState state) { } -void InterpreterMacroAssembler::dispatch_next(TosState state, int step) { +void InterpreterMacroAssembler::dispatch_next(TosState state, int step, bool generate_poll) { // load next bytecode ldrb(rscratch1, Address(pre(rbcp, step))); - dispatch_base(state, Interpreter::dispatch_table(state)); + dispatch_base(state, Interpreter::dispatch_table(state), generate_poll); } void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { @@ -1585,6 +1606,7 @@ void InterpreterMacroAssembler::call_VM_base(Register oop_result, } void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) { + assert_different_registers(obj, rscratch1); Label update, next, none; verify_oop(obj); @@ -1745,6 +1767,7 @@ void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, } void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register tmp1, Register tmp2) { + assert_different_registers(rscratch1, rscratch2, mdp, tmp1, tmp2); if (ProfileInterpreter && MethodData::profile_parameters()) { Label profile_continue, done; @@ -1752,8 +1775,8 @@ void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register t // Load the offset of the area within the MDO used for // parameters. If it's negative we're not profiling any parameters - ldr(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()))); - tbnz(tmp1, 63, profile_continue); // i.e. sign bit set + ldrw(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()))); + tbnz(tmp1, 31, profile_continue); // i.e. sign bit set // Compute a pointer to the area for parameters from the offset // and move the pointer to the slot for the last diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp index 637ae481f5b..59b33a17d22 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp @@ -55,7 +55,8 @@ class InterpreterMacroAssembler: public MacroAssembler { bool check_exceptions); // base routine for all dispatches - void dispatch_base(TosState state, address* table, bool verifyoop = true); + void dispatch_base(TosState state, address* table, + bool verifyoop = true, bool generate_poll = false); public: InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {} @@ -165,12 +166,12 @@ class InterpreterMacroAssembler: public MacroAssembler { void dispatch_prolog(TosState state, int step = 0); void dispatch_epilog(TosState state, int step = 0); // dispatch via rscratch1 - void dispatch_only(TosState state); + void dispatch_only(TosState state, bool generate_poll = false); // dispatch normal table via rscratch1 (assume rscratch1 is loaded already) void dispatch_only_normal(TosState state); void dispatch_only_noverify(TosState state); // load rscratch1 from [rbcp + step] and dispatch via rscratch1 - void dispatch_next(TosState state, int step = 0); + void dispatch_next(TosState state, int step = 0, bool generate_poll = false); // load rscratch1 from [esi] and dispatch via rscratch1 and table void dispatch_via (TosState state, address* table); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 81c00ffd106..bef4fd4e573 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -287,6 +287,40 @@ void MacroAssembler::serialize_memory(Register thread, Register tmp) { dsb(Assembler::SY); } +void MacroAssembler::safepoint_poll(Label& slow_path) { + if (SafepointMechanism::uses_thread_local_poll()) { + ldr(rscratch1, Address(rthread, Thread::polling_page_offset())); + tbnz(rscratch1, exact_log2(SafepointMechanism::poll_bit()), slow_path); + } else { + unsigned long offset; + adrp(rscratch1, ExternalAddress(SafepointSynchronize::address_of_state()), offset); + ldrw(rscratch1, Address(rscratch1, offset)); + assert(SafepointSynchronize::_not_synchronized == 0, "rewrite this code"); + cbnz(rscratch1, slow_path); + } +} + +// Just like safepoint_poll, but use an acquiring load for thread- +// local polling. +// +// We need an acquire here to ensure that any subsequent load of the +// global SafepointSynchronize::_state flag is ordered after this load +// of the local Thread::_polling page. We don't want this poll to +// return false (i.e. not safepointing) and a later poll of the global +// SafepointSynchronize::_state spuriously to return true. +// +// This is to avoid a race when we're in a native->Java transition +// racing the code which wakes up from a safepoint. +// +void MacroAssembler::safepoint_poll_acquire(Label& slow_path) { + if (SafepointMechanism::uses_thread_local_poll()) { + lea(rscratch1, Address(rthread, Thread::polling_page_offset())); + ldar(rscratch1, rscratch1); + tbnz(rscratch1, exact_log2(SafepointMechanism::poll_bit()), slow_path); + } else { + safepoint_poll(slow_path); + } +} void MacroAssembler::reset_last_Java_frame(bool clear_fp) { // we must set sp to zero to clear frame @@ -4336,15 +4370,26 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) { } -address MacroAssembler::read_polling_page(Register r, address page, relocInfo::relocType rtype) { - unsigned long off; - adrp(r, Address(page, rtype), off); - InstructionMark im(this); - code_section()->relocate(inst_mark(), rtype); - ldrw(zr, Address(r, off)); - return inst_mark(); +// Move the address of the polling page into dest. +void MacroAssembler::get_polling_page(Register dest, address page, relocInfo::relocType rtype) { + if (SafepointMechanism::uses_thread_local_poll()) { + ldr(dest, Address(rthread, Thread::polling_page_offset())); + } else { + unsigned long off; + adrp(dest, Address(page, rtype), off); + assert(off == 0, "polling page must be page aligned"); + } } +// Move the address of the polling page into r, then read the polling +// page. +address MacroAssembler::read_polling_page(Register r, address page, relocInfo::relocType rtype) { + get_polling_page(r, page, rtype); + return read_polling_page(r, rtype); +} + +// Read the polling page. The address of the polling page must +// already be in r. address MacroAssembler::read_polling_page(Register r, relocInfo::relocType rtype) { InstructionMark im(this); code_section()->relocate(inst_mark(), rtype); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index f5cab401535..94c8c037164 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -97,6 +97,9 @@ class MacroAssembler: public Assembler { virtual void check_and_handle_popframe(Register java_thread); virtual void check_and_handle_earlyret(Register java_thread); + void safepoint_poll(Label& slow_path); + void safepoint_poll_acquire(Label& slow_path); + // Biased locking support // lock_reg and obj_reg must be loaded up with the appropriate values. // swap_reg is killed. @@ -995,12 +998,12 @@ public: void atomic_xchgalw(Register prev, Register newv, Register addr); void orptr(Address adr, RegisterOrConstant src) { - ldr(rscratch2, adr); + ldr(rscratch1, adr); if (src.is_register()) - orr(rscratch2, rscratch2, src.as_register()); + orr(rscratch1, rscratch1, src.as_register()); else - orr(rscratch2, rscratch2, src.as_constant()); - str(rscratch2, adr); + orr(rscratch1, rscratch1, src.as_constant()); + str(rscratch1, adr); } // A generic CAS; success or failure is in the EQ flag. @@ -1199,6 +1202,7 @@ public: address read_polling_page(Register r, address page, relocInfo::relocType rtype); address read_polling_page(Register r, relocInfo::relocType rtype); + void get_polling_page(Register dest, address page, relocInfo::relocType rtype); // CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic. void update_byte_crc32(Register crc, Register val, Register table); diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 88e1d3d1460..6a313273ea6 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -245,6 +245,11 @@ bool NativeInstruction::is_safepoint_poll() { // mov(reg, polling_page); // ldr(zr, [reg, #offset]); // + // or + // + // ldr(reg, [rthread, #offset]); + // ldr(zr, [reg, #offset]); + // // however, we cannot rely on the polling page address load always // directly preceding the read from the page. C1 does that but C2 // has to do the load and read as two independent instruction diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 9b67fe7a5f2..0a5b696b575 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1664,7 +1664,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // critical natives they are offset down. GrowableArray arg_order(2 * total_in_args); VMRegPair tmp_vmreg; - tmp_vmreg.set1(r19->as_VMReg()); + tmp_vmreg.set2(r19->as_VMReg()); if (!is_critical_native) { for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) { @@ -1952,7 +1952,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ strw(rscratch1, Address(rthread, JavaThread::thread_state_offset())); // Force this write out before the read below - __ dmb(Assembler::SY); + __ dmb(Assembler::ISH); } else { __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset())); __ stlrw(rscratch1, rscratch2); @@ -1970,13 +1970,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // check for safepoint operation in progress and/or pending suspend requests Label safepoint_in_progress, safepoint_in_progress_done; { - assert(SafepointSynchronize::_not_synchronized == 0, "fix this code"); - unsigned long offset; - __ adrp(rscratch1, - ExternalAddress((address)SafepointSynchronize::address_of_state()), - offset); - __ ldrw(rscratch1, Address(rscratch1, offset)); - __ cbnzw(rscratch1, safepoint_in_progress); + __ safepoint_poll_acquire(safepoint_in_progress); __ ldrw(rscratch1, Address(rthread, JavaThread::suspend_flags_offset())); __ cbnzw(rscratch1, safepoint_in_progress); __ bind(safepoint_in_progress_done); @@ -2932,8 +2926,11 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t if (!cause_return) { // overwrite the return address pushed by save_live_registers - __ ldr(c_rarg0, Address(rthread, JavaThread::saved_exception_pc_offset())); - __ str(c_rarg0, Address(rfp, wordSize)); + // Additionally, r20 is a callee-saved register so we can look at + // it later to determine if someone changed the return address for + // us! + __ ldr(r20, Address(rthread, JavaThread::saved_exception_pc_offset())); + __ str(r20, Address(rfp, wordSize)); } // Do the call @@ -2968,11 +2965,40 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t // No exception case __ bind(noException); + Label no_adjust, bail; + if (SafepointMechanism::uses_thread_local_poll() && !cause_return) { + // If our stashed return pc was modified by the runtime we avoid touching it + __ ldr(rscratch1, Address(rfp, wordSize)); + __ cmp(r20, rscratch1); + __ br(Assembler::NE, no_adjust); + +#ifdef ASSERT + // Verify the correct encoding of the poll we're about to skip. + // See NativeInstruction::is_ldrw_to_zr() + __ ldrw(rscratch1, Address(r20)); + __ ubfx(rscratch2, rscratch1, 22, 10); + __ cmpw(rscratch2, 0b1011100101); + __ br(Assembler::NE, bail); + __ ubfx(rscratch2, rscratch1, 0, 5); + __ cmpw(rscratch2, 0b11111); + __ br(Assembler::NE, bail); +#endif + // Adjust return pc forward to step over the safepoint poll instruction + __ add(r20, r20, NativeInstruction::instruction_size); + __ str(r20, Address(rfp, wordSize)); + } + + __ bind(no_adjust); // Normal exit, restore registers and exit. RegisterSaver::restore_live_registers(masm, save_vectors); __ ret(lr); +#ifdef ASSERT + __ bind(bail); + __ stop("Attempting to adjust pc to skip safepoint poll but the return point is not what we expected"); +#endif + // Make sure all code is generated masm->flush(); diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 9174c554bcc..f33c6e513a8 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -414,6 +414,14 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ restore_constant_pool_cache(); __ get_method(rmethod); + if (state == atos) { + Register obj = r0; + Register mdp = r1; + Register tmp = r2; + __ ldr(mdp, Address(rmethod, Method::method_data_offset())); + __ profile_return_type(mdp, obj, tmp); + } + // Pop N words from the stack __ get_cache_and_index_at_bcp(r1, r2, 1, index_size); __ ldr(r1, Address(r1, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); @@ -967,12 +975,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { Label slow_path; // If we need a safepoint check, generate full interpreter entry. - ExternalAddress state(SafepointSynchronize::address_of_state()); - unsigned long offset; - __ adrp(rscratch1, ExternalAddress(SafepointSynchronize::address_of_state()), offset); - __ ldrw(rscratch1, Address(rscratch1, offset)); - assert(SafepointSynchronize::_not_synchronized == 0, "rewrite this code"); - __ cbnz(rscratch1, slow_path); + __ safepoint_poll(slow_path); // We don't generate local frame and don't align stack because // we call stub code and there is no safepoint on this path. @@ -986,6 +989,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { __ ldrw(val, Address(esp, 0)); // byte value __ ldrw(crc, Address(esp, wordSize)); // Initial CRC + unsigned long offset; __ adrp(tbl, ExternalAddress(StubRoutines::crc_table_addr()), offset); __ add(tbl, tbl, offset); @@ -1020,12 +1024,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI Label slow_path; // If we need a safepoint check, generate full interpreter entry. - ExternalAddress state(SafepointSynchronize::address_of_state()); - unsigned long offset; - __ adrp(rscratch1, ExternalAddress(SafepointSynchronize::address_of_state()), offset); - __ ldrw(rscratch1, Address(rscratch1, offset)); - assert(SafepointSynchronize::_not_synchronized == 0, "rewrite this code"); - __ cbnz(rscratch1, slow_path); + __ safepoint_poll(slow_path); // We don't generate local frame and don't align stack because // we call stub code and there is no safepoint on this path. @@ -1375,7 +1374,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { if (os::is_MP()) { if (UseMembar) { // Force this write out before the read below - __ dsb(Assembler::SY); + __ dmb(Assembler::ISH); } else { // Write serialization page so VM thread can do a pseudo remote membar. // We use the current thread pointer to calculate a thread specific @@ -1387,16 +1386,8 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // check for safepoint operation in progress and/or pending suspend requests { - Label Continue; - { - unsigned long offset; - __ adrp(rscratch2, SafepointSynchronize::address_of_state(), offset); - __ ldrw(rscratch2, Address(rscratch2, offset)); - } - assert(SafepointSynchronize::_not_synchronized == 0, - "SafepointSynchronize::_not_synchronized"); - Label L; - __ cbnz(rscratch2, L); + Label L, Continue; + __ safepoint_poll_acquire(L); __ ldrw(rscratch2, Address(rthread, JavaThread::suspend_flags_offset())); __ cbz(rscratch2, Continue); __ bind(L); @@ -1671,6 +1662,14 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { __ mov(rscratch2, true); __ strb(rscratch2, do_not_unlock_if_synchronized); + Label no_mdp; + Register mdp = r3; + __ ldr(mdp, Address(rmethod, Method::method_data_offset())); + __ cbz(mdp, no_mdp); + __ add(mdp, mdp, in_bytes(MethodData::data_offset())); + __ profile_parameters_type(mdp, r1, r2); + __ bind(no_mdp); + // increment invocation count & check for overflow Label invocation_counter_overflow; Label profile_method; diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index 2ba42035e7b..9390d38b1b8 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -1717,7 +1717,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) __ push_i(r1); // Adjust the bcp by the 16-bit displacement in r2 __ add(rbcp, rbcp, r2); - __ dispatch_only(vtos); + __ dispatch_only(vtos, /*generate_poll*/true); return; } @@ -1833,7 +1833,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) // continue with the bytecode @ target // rscratch1: target bytecode // rbcp: target bcp - __ dispatch_only(vtos); + __ dispatch_only(vtos, /*generate_poll*/true); if (UseLoopCounter) { if (ProfileInterpreter) { @@ -1973,7 +1973,7 @@ void TemplateTable::ret() { __ ldr(rbcp, Address(rmethod, Method::const_offset())); __ lea(rbcp, Address(rbcp, r1)); __ add(rbcp, rbcp, in_bytes(ConstMethod::codes_offset())); - __ dispatch_next(vtos); + __ dispatch_next(vtos, 0, /*generate_poll*/true); } void TemplateTable::wide_ret() { @@ -1984,7 +1984,7 @@ void TemplateTable::wide_ret() { __ ldr(rbcp, Address(rmethod, Method::const_offset())); __ lea(rbcp, Address(rbcp, r1)); __ add(rbcp, rbcp, in_bytes(ConstMethod::codes_offset())); - __ dispatch_next(vtos); + __ dispatch_next(vtos, 0, /*generate_poll*/true); } @@ -2014,7 +2014,7 @@ void TemplateTable::tableswitch() { __ rev32(r3, r3); __ load_unsigned_byte(rscratch1, Address(rbcp, r3, Address::sxtw(0))); __ add(rbcp, rbcp, r3, ext::sxtw); - __ dispatch_only(vtos); + __ dispatch_only(vtos, /*generate_poll*/true); // handle default __ bind(default_case); __ profile_switch_default(r0); @@ -2064,7 +2064,7 @@ void TemplateTable::fast_linearswitch() { __ rev32(r3, r3); __ add(rbcp, rbcp, r3, ext::sxtw); __ ldrb(rscratch1, Address(rbcp, 0)); - __ dispatch_only(vtos); + __ dispatch_only(vtos, /*generate_poll*/true); } void TemplateTable::fast_binaryswitch() { @@ -2162,7 +2162,7 @@ void TemplateTable::fast_binaryswitch() { __ rev32(j, j); __ load_unsigned_byte(rscratch1, Address(rbcp, j, Address::sxtw(0))); __ lea(rbcp, Address(rbcp, j, Address::sxtw(0))); - __ dispatch_only(vtos); + __ dispatch_only(vtos, /*generate_poll*/true); // default case -> j = default offset __ bind(default_case); @@ -2171,7 +2171,7 @@ void TemplateTable::fast_binaryswitch() { __ rev32(j, j); __ load_unsigned_byte(rscratch1, Address(rbcp, j, Address::sxtw(0))); __ lea(rbcp, Address(rbcp, j, Address::sxtw(0))); - __ dispatch_only(vtos); + __ dispatch_only(vtos, /*generate_poll*/true); } diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 76d750a6942..33e78cd8914 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -394,4 +394,6 @@ void VM_Version::initialize() { g.generate_getPsrInfo()); get_processor_features(); + + UNSUPPORTED_OPTION(CriticalJNINatives); } diff --git a/src/hotspot/cpu/arm/stubGenerator_arm.cpp b/src/hotspot/cpu/arm/stubGenerator_arm.cpp index 97ef93c2e4f..ec1a6d8279d 100644 --- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp @@ -2968,7 +2968,9 @@ class StubGenerator: public StubCodeGenerator { CardTableModRefBS* ct = barrier_set_cast(bs); assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - Label L_cardtable_loop; + Label L_cardtable_loop, L_done; + + __ cbz_32(count, L_done); // zero count - nothing to do __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop); __ sub(count, count, BytesPerHeapOop); // last addr @@ -2987,6 +2989,7 @@ class StubGenerator: public StubCodeGenerator { __ strb(zero, Address(addr, 1, post_indexed)); __ subs(count, count, 1); __ b(L_cardtable_loop, ge); + __ BIND(L_done); } break; case BarrierSet::ModRef: diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 631b20b81a5..875c5dfdfdf 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -41,20 +41,25 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { const Register temp_reg = R12_scratch2; + Label Lmiss; + verify_oop(receiver); + MacroAssembler::null_check(receiver, oopDesc::klass_offset_in_bytes(), &Lmiss); load_klass(temp_reg, receiver); - if (TrapBasedICMissChecks) { + + if (TrapBasedICMissChecks && TrapBasedNullChecks) { trap_ic_miss_check(temp_reg, iCache); } else { - Label L; + Label Lok; cmpd(CCR0, temp_reg, iCache); - beq(CCR0, L); + 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(L); + bind(Lok); } } diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index 282ffeb218b..c7fdc9d7e23 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -3371,7 +3371,7 @@ void TemplateTable::invokevirtual(int byte_no) { __ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_vfinal_shift); __ bfalse(CCR0, LnotFinal); - if (RewriteBytecodes && !UseSharedSpaces) { + if (RewriteBytecodes && !UseSharedSpaces && !DumpSharedSpaces) { patch_bytecode(Bytecodes::_fast_invokevfinal, Rnew_bc, R12_scratch2); } invokevfinal_helper(Rvtableindex_or_method, Rflags, R11_scratch1, R12_scratch2); diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp index a839700259c..9900adbfebc 100644 --- a/src/hotspot/cpu/s390/assembler_s390.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.hpp @@ -582,7 +582,11 @@ class Assembler : public AbstractAssembler { #define LOC_ZOPC (unsigned long)(0xebL << 40 | 0xf2L) // z196 #define LOCG_ZOPC (unsigned long)(0xebL << 40 | 0xe2L) // z196 -#define LMG_ZOPC (unsigned long)(235L << 40 | 4L) + +// LOAD multiple registers at once +#define LM_ZOPC (unsigned int)(0x98 << 24) +#define LMY_ZOPC (unsigned long)(0xebL << 40 | 0x98L) +#define LMG_ZOPC (unsigned long)(0xebL << 40 | 0x04L) #define LE_ZOPC (unsigned int)(0x78 << 24) #define LEY_ZOPC (unsigned long)(237L << 40 | 100L) @@ -613,7 +617,10 @@ class Assembler : public AbstractAssembler { #define STOC_ZOPC (unsigned long)(0xebL << 40 | 0xf3L) // z196 #define STOCG_ZOPC (unsigned long)(0xebL << 40 | 0xe3L) // z196 -#define STMG_ZOPC (unsigned long)(235L << 40 | 36L) +// STORE multiple registers at once +#define STM_ZOPC (unsigned int)(0x90 << 24) +#define STMY_ZOPC (unsigned long)(0xebL << 40 | 0x90L) +#define STMG_ZOPC (unsigned long)(0xebL << 40 | 0x24L) #define STE_ZOPC (unsigned int)(0x70 << 24) #define STEY_ZOPC (unsigned long)(237L << 40 | 102L) @@ -874,15 +881,19 @@ class Assembler : public AbstractAssembler { // Shift // arithmetic -#define SLA_ZOPC (unsigned int)(139 << 24) -#define SLAG_ZOPC (unsigned long)(235L << 40 | 11L) -#define SRA_ZOPC (unsigned int)(138 << 24) -#define SRAG_ZOPC (unsigned long)(235L << 40 | 10L) +#define SLA_ZOPC (unsigned int)(0x8b << 24) +#define SLAK_ZOPC (unsigned long)(0xebL << 40 | 0xddL) +#define SLAG_ZOPC (unsigned long)(0xebL << 40 | 0x0bL) +#define SRA_ZOPC (unsigned int)(0x8a << 24) +#define SRAK_ZOPC (unsigned long)(0xebL << 40 | 0xdcL) +#define SRAG_ZOPC (unsigned long)(0xebL << 40 | 0x0aL) // logical -#define SLL_ZOPC (unsigned int)(137 << 24) -#define SLLG_ZOPC (unsigned long)(235L << 40 | 13L) -#define SRL_ZOPC (unsigned int)(136 << 24) -#define SRLG_ZOPC (unsigned long)(235L << 40 | 12L) +#define SLL_ZOPC (unsigned int)(0x89 << 24) +#define SLLK_ZOPC (unsigned long)(0xebL << 40 | 0xdfL) +#define SLLG_ZOPC (unsigned long)(0xebL << 40 | 0x0dL) +#define SRL_ZOPC (unsigned int)(0x88 << 24) +#define SRLK_ZOPC (unsigned long)(0xebL << 40 | 0xdeL) +#define SRLG_ZOPC (unsigned long)(0xebL << 40 | 0x0cL) // Rotate, then AND/XOR/OR/insert // rotate @@ -2262,12 +2273,16 @@ class Assembler : public AbstractAssembler { // shift inline void z_sla( Register r1, int64_t d2, Register b2=Z_R0); // shift left r1 = r1 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved! + inline void z_slak(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved! inline void z_slag(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int64, only 63 bits shifted, sign preserved! inline void z_sra( Register r1, int64_t d2, Register b2=Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, sign extended + inline void z_srak(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, sign extended inline void z_srag(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, sign extended inline void z_sll( Register r1, int64_t d2, Register b2=Z_R0); // shift left r1 = r1 << ((d2+b2)&0x3f) ; int32, zeros added + inline void z_sllk(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int32, zeros added inline void z_sllg(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int64, zeros added inline void z_srl( Register r1, int64_t d2, Register b2=Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, zero extended + inline void z_srlk(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, zero extended inline void z_srlg(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, zero extended // rotate @@ -3035,7 +3050,11 @@ class Assembler : public AbstractAssembler { inline void z_tam(); inline void z_stckf(int64_t d2, Register b2); + inline void z_stm( Register r1, Register r3, int64_t d2, Register b2); + inline void z_stmy(Register r1, Register r3, int64_t d2, Register b2); inline void z_stmg(Register r1, Register r3, int64_t d2, Register b2); + inline void z_lm( Register r1, Register r3, int64_t d2, Register b2); + inline void z_lmy(Register r1, Register r3, int64_t d2, Register b2); inline void z_lmg(Register r1, Register r3, int64_t d2, Register b2); inline void z_cs( Register r1, Register r3, int64_t d2, Register b2); diff --git a/src/hotspot/cpu/s390/assembler_s390.inline.hpp b/src/hotspot/cpu/s390/assembler_s390.inline.hpp index 19c472787c5..583d86e18b0 100644 --- a/src/hotspot/cpu/s390/assembler_s390.inline.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.inline.hpp @@ -334,12 +334,16 @@ inline void Assembler::z_stfle(int64_t d2, Register b2) { emit_32(STFLE_ZOPC | u // SHIFT/RORATE OPERATIONS //----------------------------------- inline void Assembler::z_sla( Register r1, int64_t d2, Register b2) { emit_32( SLA_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } +inline void Assembler::z_slak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } inline void Assembler::z_slag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } inline void Assembler::z_sra( Register r1, int64_t d2, Register b2) { emit_32( SRA_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } +inline void Assembler::z_srak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } inline void Assembler::z_srag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } inline void Assembler::z_sll( Register r1, int64_t d2, Register b2) { emit_32( SLL_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } +inline void Assembler::z_sllk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } inline void Assembler::z_sllg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } inline void Assembler::z_srl( Register r1, int64_t d2, Register b2) { emit_32( SRL_ZOPC | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); } +inline void Assembler::z_srlk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLK_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } inline void Assembler::z_srlg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLG_ZOPC | regt(r1, 8, 48) | simm20(d2) | reg(b2, 16, 48) | reg(r3, 12, 48)); } // rotate left @@ -690,10 +694,14 @@ inline void Assembler::z_ahhlr(Register r1, Register r2, Register r3) { emit_32( inline void Assembler::z_tam() { emit_16( TAM_ZOPC); } inline void Assembler::z_stckf(int64_t d2, Register b2) { emit_32( STCKF_ZOPC | uimm12(d2, 20, 32) | regz(b2, 16, 32)); } -inline void Assembler::z_stmg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMG_ZOPC | simm20(d2) | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) ); } -inline void Assembler::z_lmg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMG_ZOPC | simm20(d2) | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) ); } +inline void Assembler::z_stm( Register r1, Register r3, int64_t d2, Register b2) { emit_32( STM_ZOPC | reg(r1, 8, 32) | reg(r3,12,32)| reg(b2,16,32) | uimm12(d2, 20,32)); } +inline void Assembler::z_stmy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMY_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } +inline void Assembler::z_stmg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMG_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } +inline void Assembler::z_lm( Register r1, Register r3, int64_t d2, Register b2) { emit_32( LM_ZOPC | reg(r1, 8, 32) | reg(r3,12,32)| reg(b2,16,32) | uimm12(d2, 20,32)); } +inline void Assembler::z_lmy( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMY_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } +inline void Assembler::z_lmg( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMG_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); } -inline void Assembler::z_cs(Register r1, Register r3, int64_t d2, Register b2) { emit_32( CS_ZOPC | regt(r1, 8, 32) | reg(r3, 12, 32) | reg(b2, 16, 32) | uimm12(d2, 20, 32)); } +inline void Assembler::z_cs( Register r1, Register r3, int64_t d2, Register b2) { emit_32( CS_ZOPC | regt(r1, 8, 32) | reg(r3, 12, 32) | reg(b2, 16, 32) | uimm12(d2, 20, 32)); } inline void Assembler::z_csy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSY_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | reg(b2, 16, 48) | simm20(d2)); } inline void Assembler::z_csg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | reg(b2, 16, 48) | simm20(d2)); } inline void Assembler::z_cs( Register r1, Register r3, const Address& a) { assert(!a.has_index(), "Cannot encode index"); z_cs( r1, r3, a.disp(), a.baseOrR0()); } diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index af2c02934ff..afc7a7667e2 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -936,7 +936,7 @@ void MacroAssembler::load_long_pcrelative(Register Rdst, address dataLocation) { // Some extra safety net. if (!RelAddr::is_in_range_of_RelAddr32(total_distance)) { - guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "too far away"); + guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "load_long_pcrelative can't handle distance " INTPTR_FORMAT, total_distance); } (this)->relocate(rspec, relocInfo::pcrel_addr_format); @@ -956,7 +956,7 @@ void MacroAssembler::load_addr_pcrelative(Register Rdst, address addrLocation) { // Some extra safety net. if (!RelAddr::is_in_range_of_RelAddr32(total_distance)) { - guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "too far away"); + guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "load_long_pcrelative can't handle distance " INTPTR_FORMAT, total_distance); } (this)->relocate(rspec, relocInfo::pcrel_addr_format); @@ -1025,6 +1025,13 @@ void MacroAssembler::testbit(Register r, unsigned int bitPos) { } } +void MacroAssembler::prefetch_read(Address a) { + z_pfd(1, a.disp20(), a.indexOrR0(), a.base()); +} +void MacroAssembler::prefetch_update(Address a) { + z_pfd(2, a.disp20(), a.indexOrR0(), a.base()); +} + // Clear a register, i.e. load const zero into reg. // Return len (in bytes) of generated instruction(s). // whole_reg: Clear 64 bits if true, 32 bits otherwise. @@ -4896,77 +4903,296 @@ unsigned int MacroAssembler::CopyRawMemory_AlignedDisjoint(Register src_reg, Reg // Intrinsics for CompactStrings -// Compress char[] to byte[]. odd_reg contains cnt. Kills dst. Early clobber: result +// Compress char[] to byte[]. +// Restores: src, dst +// Uses: cnt +// Kills: tmp, Z_R0, Z_R1. +// Early clobber: result. +// Note: +// cnt is signed int. Do not rely on high word! +// counts # characters, not bytes. // The result is the number of characters copied before the first incompatible character was found. -// If tmp2 is provided and the compression fails, the compression stops exactly at this point and the result is precise. +// If precise is true, the processing stops exactly at this point. Otherwise, the result may be off +// by a few bytes. The result always indicates the number of copied characters. // // Note: Does not behave exactly like package private StringUTF16 compress java implementation in case of failure: -// - Different number of characters may have been written to dead array (if tmp2 not provided). +// - Different number of characters may have been written to dead array (if precise is false). // - Returns a number --- + // Strings with 4 and 8 characters were fond to occur very frequently. + // Therefore, we handle them right away with minimal overhead. + Label skipShortcut, skip4Shortcut, skip8Shortcut; + Register Rout = Z_R0; + z_chi(Rcnt, 4); + z_brne(skip4Shortcut); // 4 characters are very frequent + z_lg(Z_R0, 0, Rsrc); // Treat exactly 4 characters specially. + if (VM_Version::has_DistinctOpnds()) { + Rout = Z_R0; + z_ngrk(Rix, Z_R0, Rmask); + } else { + Rout = Rix; + z_lgr(Rix, Z_R0); + z_ngr(Z_R0, Rmask); + } + z_brnz(skipShortcut); + z_stcmh(Rout, 5, 0, Rdst); + z_stcm(Rout, 5, 2, Rdst); + z_lgfr(result, Rcnt); + z_bru(AllDone); + bind(skip4Shortcut); + + z_chi(Rcnt, 8); + z_brne(skip8Shortcut); // There's more to do... + z_lmg(Z_R0, Z_R1, 0, Rsrc); // Treat exactly 8 characters specially. + if (VM_Version::has_DistinctOpnds()) { + Rout = Z_R0; + z_ogrk(Rix, Z_R0, Z_R1); + z_ngr(Rix, Rmask); + } else { + Rout = Rix; + z_lgr(Rix, Z_R0); + z_ogr(Z_R0, Z_R1); + z_ngr(Z_R0, Rmask); + } + z_brnz(skipShortcut); + z_stcmh(Rout, 5, 0, Rdst); + z_stcm(Rout, 5, 2, Rdst); + z_stcmh(Z_R1, 5, 4, Rdst); + z_stcm(Z_R1, 5, 6, Rdst); + z_lgfr(result, Rcnt); + z_bru(AllDone); + + bind(skip8Shortcut); + clear_reg(Z_R0, true, false); // #characters already processed (none). Precond for scalar loop. + z_brl(ScalarShortcut); // Just a few characters + + bind(skipShortcut); + } +#endif + clear_reg(Z_R0); // make sure register is properly initialized. + + if (VM_Version::has_VectorFacility()) { + const int min_vcnt = 32; // Minimum #characters required to use vector instructions. + // Otherwise just do nothing in vector mode. + // Must be multiple of 2*(vector register length in chars (8 HW = 128 bits)). + const int log_min_vcnt = exact_log2(min_vcnt); + Label VectorLoop, VectorDone, VectorBreak; + + VectorRegister Vtmp1 = Z_V16; + VectorRegister Vtmp2 = Z_V17; + VectorRegister Vmask = Z_V18; + VectorRegister Vzero = Z_V19; + VectorRegister Vsrc_first = Z_V20; + VectorRegister Vsrc_last = Z_V23; + + assert((Vsrc_last->encoding() - Vsrc_first->encoding() + 1) == min_vcnt/8, "logic error"); + assert(VM_Version::has_DistinctOpnds(), "Assumption when has_VectorFacility()"); + z_srak(Rix, Rcnt, log_min_vcnt); // # vector loop iterations + z_brz(VectorDone); // not enough data for vector loop + + z_vzero(Vzero); // all zeroes + z_vgmh(Vmask, 0, 7); // generate 0xff00 mask for all 2-byte elements + z_sllg(Z_R0, Rix, log_min_vcnt); // remember #chars that will be processed by vector loop + + bind(VectorLoop); + z_vlm(Vsrc_first, Vsrc_last, 0, Rsrc); + add2reg(Rsrc, min_vcnt*2); + + //---< check for incompatible character >--- + z_vo(Vtmp1, Z_V20, Z_V21); + z_vo(Vtmp2, Z_V22, Z_V23); + z_vo(Vtmp1, Vtmp1, Vtmp2); + z_vn(Vtmp1, Vtmp1, Vmask); + z_vceqhs(Vtmp1, Vtmp1, Vzero); // high half of all chars must be zero for successful compress. + z_brne(VectorBreak); // break vector loop, incompatible character found. + // re-process data from current iteration in break handler. + + //---< pack & store characters >--- + z_vpkh(Vtmp1, Z_V20, Z_V21); // pack (src1, src2) -> tmp1 + z_vpkh(Vtmp2, Z_V22, Z_V23); // pack (src3, src4) -> tmp2 + z_vstm(Vtmp1, Vtmp2, 0, Rdst); // store packed string + add2reg(Rdst, min_vcnt); + + z_brct(Rix, VectorLoop); + + z_bru(VectorDone); + + bind(VectorBreak); + add2reg(Rsrc, -min_vcnt*2); // Fix Rsrc. Rsrc was already updated, but Rdst and Rix are not. + z_sll(Rix, log_min_vcnt); // # chars processed so far in VectorLoop, excl. current iteration. + z_sr(Z_R0, Rix); // correct # chars processed in total. + + bind(VectorDone); + } + + { + const int min_cnt = 8; // Minimum #characters required to use unrolled loop. + // Otherwise just do nothing in unrolled loop. + // Must be multiple of 8. + const int log_min_cnt = exact_log2(min_cnt); + Label UnrolledLoop, UnrolledDone, UnrolledBreak; + if (VM_Version::has_DistinctOpnds()) { - z_ogrk(tmp2, Z_R0, Z_R1); + z_srk(Rix, Rcnt, Z_R0); // remaining # chars to compress in unrolled loop } else { - z_lgr(tmp2, Z_R0); - z_ogr(tmp2, Z_R1); + z_lr(Rix, Rcnt); + z_sr(Rix, Z_R0); } - z_ngr(tmp2, mask); - z_brne(Lslow); // Failed fast case, retry slowly. + z_sra(Rix, log_min_cnt); // unrolled loop count + z_brz(UnrolledDone); + + bind(UnrolledLoop); + z_lmg(Z_R0, Z_R1, 0, Rsrc); + if (precise) { + z_ogr(Z_R1, Z_R0); // check all 8 chars for incompatibility + z_ngr(Z_R1, Rmask); + z_brnz(UnrolledBreak); + + z_lg(Z_R1, 8, Rsrc); // reload destroyed register + z_stcmh(Z_R0, 5, 0, Rdst); + z_stcm(Z_R0, 5, 2, Rdst); + } else { + z_stcmh(Z_R0, 5, 0, Rdst); + z_stcm(Z_R0, 5, 2, Rdst); + + z_ogr(Z_R0, Z_R1); + z_ngr(Z_R0, Rmask); + z_brnz(UnrolledBreak); + } + z_stcmh(Z_R1, 5, 4, Rdst); + z_stcm(Z_R1, 5, 6, Rdst); + + add2reg(Rsrc, min_cnt*2); + add2reg(Rdst, min_cnt); + z_brct(Rix, UnrolledLoop); + + z_lgfr(Z_R0, Rcnt); // # chars processed in total after unrolled loop. + z_nilf(Z_R0, ~(min_cnt-1)); + z_tmll(Rcnt, min_cnt-1); + z_brnaz(ScalarShortcut); // if all bits zero, there is nothing left to do for scalar loop. + // Rix == 0 in all cases. + z_lgfr(result, Rcnt); // all characters processed. + z_sgfr(Rdst, Rcnt); // restore ptr + z_sgfr(Rsrc, Rcnt); // restore ptr, double the element count for Rsrc restore + z_sgfr(Rsrc, Rcnt); + z_bru(AllDone); + + bind(UnrolledBreak); + z_lgfr(Z_R0, Rcnt); // # chars processed in total after unrolled loop + z_nilf(Z_R0, ~(min_cnt-1)); + z_sll(Rix, log_min_cnt); // # chars processed so far in UnrolledLoop, excl. current iteration. + z_sr(Z_R0, Rix); // correct # chars processed in total. + if (!precise) { + z_lgfr(result, Z_R0); + z_aghi(result, min_cnt/2); // min_cnt/2 characters have already been written + // but ptrs were not updated yet. + z_sgfr(Rdst, Z_R0); // restore ptr + z_sgfr(Rsrc, Z_R0); // restore ptr, double the element count for Rsrc restore + z_sgfr(Rsrc, Z_R0); + z_bru(AllDone); + } + bind(UnrolledDone); } - z_stcmh(Z_R0, 5, 0, addr2); - z_stcm(Z_R0, 5, 2, addr2); - if (!precise) { z_ogr(Z_R0, Z_R1); } - z_stcmh(Z_R1, 5, 4, addr2); - z_stcm(Z_R1, 5, 6, addr2); - if (!precise) { - z_ngr(Z_R0, mask); - z_brne(Ldone); // Failed (more than needed was written). + + { + Label ScalarLoop, ScalarDone, ScalarBreak; + + bind(ScalarShortcut); + z_ltgfr(result, Rcnt); + z_brz(AllDone); + +#if 0 // Sacrifice shortcuts for code compactness + { + //---< Special treatment for very short strings (one or two characters) >--- + // For these strings, we are sure that the above code was skipped. + // Thus, no registers were modified, register restore is not required. + Label ScalarDoit, Scalar2Char; + z_chi(Rcnt, 2); + z_brh(ScalarDoit); + z_llh(Z_R1, 0, Z_R0, Rsrc); + z_bre(Scalar2Char); + z_tmll(Z_R1, 0xff00); + z_lghi(result, 0); // cnt == 1, first char invalid, no chars successfully processed + z_brnaz(AllDone); + z_stc(Z_R1, 0, Z_R0, Rdst); + z_lghi(result, 1); + z_bru(AllDone); + + bind(Scalar2Char); + z_llh(Z_R0, 2, Z_R0, Rsrc); + z_tmll(Z_R1, 0xff00); + z_lghi(result, 0); // cnt == 2, first char invalid, no chars successfully processed + z_brnaz(AllDone); + z_stc(Z_R1, 0, Z_R0, Rdst); + z_tmll(Z_R0, 0xff00); + z_lghi(result, 1); // cnt == 2, second char invalid, one char successfully processed + z_brnaz(AllDone); + z_stc(Z_R0, 1, Z_R0, Rdst); + z_lghi(result, 2); + z_bru(AllDone); + + bind(ScalarDoit); + } +#endif + + if (VM_Version::has_DistinctOpnds()) { + z_srk(Rix, Rcnt, Z_R0); // remaining # chars to compress in unrolled loop + } else { + z_lr(Rix, Rcnt); + z_sr(Rix, Z_R0); + } + z_lgfr(result, Rcnt); // # processed characters (if all runs ok). + z_brz(ScalarDone); + + bind(ScalarLoop); + z_llh(Z_R1, 0, Z_R0, Rsrc); + z_tmll(Z_R1, 0xff00); + z_brnaz(ScalarBreak); + z_stc(Z_R1, 0, Z_R0, Rdst); + add2reg(Rsrc, 2); + add2reg(Rdst, 1); + z_brct(Rix, ScalarLoop); + + z_bru(ScalarDone); + + bind(ScalarBreak); + z_sr(result, Rix); + + bind(ScalarDone); + z_sgfr(Rdst, result); // restore ptr + z_sgfr(Rsrc, result); // restore ptr, double the element count for Rsrc restore + z_sgfr(Rsrc, result); } - z_aghi(addr2, 8); - z_brxle(ind1, even_reg, Lloop1); - - bind(Lslow); - // Compute index limit and skip if negative. - z_ahi(odd_reg, 16-2); // Last possible index for slow loop. - z_lhi(even_reg, 2); - z_cr(ind1, odd_reg); - z_brh(Ldone); - - bind(Lloop2); // 1 Character per iteration. - z_llh(Z_R0, Address(src, ind1)); - z_tmll(Z_R0, 0xFF00); - z_brnaz(Ldone); // Failed slow case: Return number of written characters. - z_stc(Z_R0, Address(addr2)); - z_aghi(addr2, 1); - z_brxle(ind1, even_reg, Lloop2); - - bind(Ldone); // result = ind1 = 2*cnt - z_srl(ind1, 1); - - BLOCK_COMMENT("} string_compress"); + bind(AllDone); + if (precise) { + BLOCK_COMMENT("} encode_iso_array"); + } else { + BLOCK_COMMENT("} string_compress"); + } return offset() - block_start; } @@ -4997,53 +5223,432 @@ unsigned int MacroAssembler::string_inflate_trot(Register src, Register dst, Reg return offset() - block_start; } -// Inflate byte[] to char[]. odd_reg contains cnt. Kills src. -unsigned int MacroAssembler::string_inflate(Register src, Register dst, Register odd_reg, - Register even_reg, Register tmp) { - int block_start = offset(); +// Inflate byte[] to char[]. +// Restores: src, dst +// Uses: cnt +// Kills: tmp, Z_R0, Z_R1. +// Note: +// cnt is signed int. Do not rely on high word! +// counts # characters, not bytes. +unsigned int MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp) { + assert_different_registers(Z_R0, Z_R1, src, dst, cnt, tmp); BLOCK_COMMENT("string_inflate {"); + int block_start = offset(); - Label Lloop1, Lloop2, Lslow, Ldone; - const Register addr1 = src, ind2 = tmp; + Register Rcnt = cnt; // # characters (src: bytes, dst: char (2-byte)), remaining after current loop. + Register Rix = tmp; // loop index + Register Rsrc = src; // addr(src array) + Register Rdst = dst; // addr(dst array) + Label ScalarShortcut, AllDone; - z_sll(odd_reg, 1); // Number of bytes to write. (Must be a positive simm32.) - clear_reg(ind2); // Index to write. - z_ahi(odd_reg, -16); // Last possible index for fast loop. - z_brl(Lslow); +#if 0 // Sacrifice shortcuts for code compactness + { + //---< shortcuts for short strings (very frequent) >--- + Label skipShortcut, skip4Shortcut; + z_ltr(Rcnt, Rcnt); // absolutely nothing to do for strings of len == 0. + z_brz(AllDone); + clear_reg(Z_R0); // make sure registers are properly initialized. + clear_reg(Z_R1); + z_chi(Rcnt, 4); + z_brne(skip4Shortcut); // 4 characters are very frequent + z_icm(Z_R0, 5, 0, Rsrc); // Treat exactly 4 characters specially. + z_icm(Z_R1, 5, 2, Rsrc); + z_stm(Z_R0, Z_R1, 0, Rdst); + z_bru(AllDone); + bind(skip4Shortcut); - // ind2: index, even_reg: index increment, odd_reg: index limit - clear_reg(Z_R0); - clear_reg(Z_R1); - z_lhi(even_reg, 16); + z_chi(Rcnt, 8); + z_brh(skipShortcut); // There's a lot to do... + z_lgfr(Z_R0, Rcnt); // remaining #characters (<= 8). Precond for scalar loop. + // This does not destroy the "register cleared" state of Z_R0. + z_brl(ScalarShortcut); // Just a few characters + z_icmh(Z_R0, 5, 0, Rsrc); // Treat exactly 8 characters specially. + z_icmh(Z_R1, 5, 4, Rsrc); + z_icm(Z_R0, 5, 2, Rsrc); + z_icm(Z_R1, 5, 6, Rsrc); + z_stmg(Z_R0, Z_R1, 0, Rdst); + z_bru(AllDone); + bind(skipShortcut); + } +#endif + clear_reg(Z_R0); // make sure register is properly initialized. - bind(Lloop1); // 8 Characters per iteration. - z_icmh(Z_R0, 5, 0, addr1); - z_icmh(Z_R1, 5, 4, addr1); - z_icm(Z_R0, 5, 2, addr1); - z_icm(Z_R1, 5, 6, addr1); - z_aghi(addr1, 8); - z_stg(Z_R0, Address(dst, ind2)); - z_stg(Z_R1, Address(dst, ind2, 8)); - z_brxle(ind2, even_reg, Lloop1); + if (VM_Version::has_VectorFacility()) { + const int min_vcnt = 32; // Minimum #characters required to use vector instructions. + // Otherwise just do nothing in vector mode. + // Must be multiple of vector register length (16 bytes = 128 bits). + const int log_min_vcnt = exact_log2(min_vcnt); + Label VectorLoop, VectorDone; - bind(Lslow); - // Compute index limit and skip if negative. - z_ahi(odd_reg, 16-2); // Last possible index for slow loop. - z_lhi(even_reg, 2); - z_cr(ind2, odd_reg); - z_brh(Ldone); + assert(VM_Version::has_DistinctOpnds(), "Assumption when has_VectorFacility()"); + z_srak(Rix, Rcnt, log_min_vcnt); // calculate # vector loop iterations + z_brz(VectorDone); // skip if none - bind(Lloop2); // 1 Character per iteration. - z_llc(Z_R0, Address(addr1)); - z_sth(Z_R0, Address(dst, ind2)); - z_aghi(addr1, 1); - z_brxle(ind2, even_reg, Lloop2); + z_sllg(Z_R0, Rix, log_min_vcnt); // remember #chars that will be processed by vector loop - bind(Ldone); + bind(VectorLoop); + z_vlm(Z_V20, Z_V21, 0, Rsrc); // get next 32 characters (single-byte) + add2reg(Rsrc, min_vcnt); + + z_vuplhb(Z_V22, Z_V20); // V2 <- (expand) V0(high) + z_vupllb(Z_V23, Z_V20); // V3 <- (expand) V0(low) + z_vuplhb(Z_V24, Z_V21); // V4 <- (expand) V1(high) + z_vupllb(Z_V25, Z_V21); // V5 <- (expand) V1(low) + z_vstm(Z_V22, Z_V25, 0, Rdst); // store next 32 bytes + add2reg(Rdst, min_vcnt*2); + + z_brct(Rix, VectorLoop); + + bind(VectorDone); + } + + const int min_cnt = 8; // Minimum #characters required to use unrolled scalar loop. + // Otherwise just do nothing in unrolled scalar mode. + // Must be multiple of 8. + { + const int log_min_cnt = exact_log2(min_cnt); + Label UnrolledLoop, UnrolledDone; + + + if (VM_Version::has_DistinctOpnds()) { + z_srk(Rix, Rcnt, Z_R0); // remaining # chars to process in unrolled loop + } else { + z_lr(Rix, Rcnt); + z_sr(Rix, Z_R0); + } + z_sra(Rix, log_min_cnt); // unrolled loop count + z_brz(UnrolledDone); + + clear_reg(Z_R0); + clear_reg(Z_R1); + + bind(UnrolledLoop); + z_icmh(Z_R0, 5, 0, Rsrc); + z_icmh(Z_R1, 5, 4, Rsrc); + z_icm(Z_R0, 5, 2, Rsrc); + z_icm(Z_R1, 5, 6, Rsrc); + add2reg(Rsrc, min_cnt); + + z_stmg(Z_R0, Z_R1, 0, Rdst); + + add2reg(Rdst, min_cnt*2); + z_brct(Rix, UnrolledLoop); + + bind(UnrolledDone); + z_lgfr(Z_R0, Rcnt); // # chars left over after unrolled loop. + z_nilf(Z_R0, min_cnt-1); + z_brnz(ScalarShortcut); // if zero, there is nothing left to do for scalar loop. + // Rix == 0 in all cases. + z_sgfr(Z_R0, Rcnt); // negative # characters the ptrs have been advanced previously. + z_agr(Rdst, Z_R0); // restore ptr, double the element count for Rdst restore. + z_agr(Rdst, Z_R0); + z_agr(Rsrc, Z_R0); // restore ptr. + z_bru(AllDone); + } + + { + bind(ScalarShortcut); + // Z_R0 must contain remaining # characters as 64-bit signed int here. + // register contents is preserved over scalar processing (for register fixup). + +#if 0 // Sacrifice shortcuts for code compactness + { + Label ScalarDefault; + z_chi(Rcnt, 2); + z_brh(ScalarDefault); + z_llc(Z_R0, 0, Z_R0, Rsrc); // 6 bytes + z_sth(Z_R0, 0, Z_R0, Rdst); // 4 bytes + z_brl(AllDone); + z_llc(Z_R0, 1, Z_R0, Rsrc); // 6 bytes + z_sth(Z_R0, 2, Z_R0, Rdst); // 4 bytes + z_bru(AllDone); + bind(ScalarDefault); + } +#endif + + Label CodeTable; + // Some comments on Rix calculation: + // - Rcnt is small, therefore no bits shifted out of low word (sll(g) instructions). + // - high word of both Rix and Rcnt may contain garbage + // - the final lngfr takes care of that garbage, extending the sign to high word + z_sllg(Rix, Z_R0, 2); // calculate 10*Rix = (4*Rix + Rix)*2 + z_ar(Rix, Z_R0); + z_larl(Z_R1, CodeTable); + z_sll(Rix, 1); + z_lngfr(Rix, Rix); // ix range: [0..7], after inversion & mult: [-(7*12)..(0*12)]. + z_bc(Assembler::bcondAlways, 0, Rix, Z_R1); + + z_llc(Z_R1, 6, Z_R0, Rsrc); // 6 bytes + z_sth(Z_R1, 12, Z_R0, Rdst); // 4 bytes + + z_llc(Z_R1, 5, Z_R0, Rsrc); + z_sth(Z_R1, 10, Z_R0, Rdst); + + z_llc(Z_R1, 4, Z_R0, Rsrc); + z_sth(Z_R1, 8, Z_R0, Rdst); + + z_llc(Z_R1, 3, Z_R0, Rsrc); + z_sth(Z_R1, 6, Z_R0, Rdst); + + z_llc(Z_R1, 2, Z_R0, Rsrc); + z_sth(Z_R1, 4, Z_R0, Rdst); + + z_llc(Z_R1, 1, Z_R0, Rsrc); + z_sth(Z_R1, 2, Z_R0, Rdst); + + z_llc(Z_R1, 0, Z_R0, Rsrc); + z_sth(Z_R1, 0, Z_R0, Rdst); + bind(CodeTable); + + z_chi(Rcnt, 8); // no fixup for small strings. Rdst, Rsrc were not modified. + z_brl(AllDone); + + z_sgfr(Z_R0, Rcnt); // # characters the ptrs have been advanced previously. + z_agr(Rdst, Z_R0); // restore ptr, double the element count for Rdst restore. + z_agr(Rdst, Z_R0); + z_agr(Rsrc, Z_R0); // restore ptr. + } + bind(AllDone); BLOCK_COMMENT("} string_inflate"); + return offset() - block_start; +} +// Inflate byte[] to char[], length known at compile time. +// Restores: src, dst +// Kills: tmp, Z_R0, Z_R1. +// Note: +// len is signed int. Counts # characters, not bytes. +unsigned int MacroAssembler::string_inflate_const(Register src, Register dst, Register tmp, int len) { + assert_different_registers(Z_R0, Z_R1, src, dst, tmp); + + BLOCK_COMMENT("string_inflate_const {"); + int block_start = offset(); + + Register Rix = tmp; // loop index + Register Rsrc = src; // addr(src array) + Register Rdst = dst; // addr(dst array) + Label ScalarShortcut, AllDone; + int nprocessed = 0; + int src_off = 0; // compensate for saved (optimized away) ptr advancement. + int dst_off = 0; // compensate for saved (optimized away) ptr advancement. + bool restore_inputs = false; + bool workreg_clear = false; + + if ((len >= 32) && VM_Version::has_VectorFacility()) { + const int min_vcnt = 32; // Minimum #characters required to use vector instructions. + // Otherwise just do nothing in vector mode. + // Must be multiple of vector register length (16 bytes = 128 bits). + const int log_min_vcnt = exact_log2(min_vcnt); + const int iterations = (len - nprocessed) >> log_min_vcnt; + nprocessed += iterations << log_min_vcnt; + Label VectorLoop; + + if (iterations == 1) { + z_vlm(Z_V20, Z_V21, 0+src_off, Rsrc); // get next 32 characters (single-byte) + z_vuplhb(Z_V22, Z_V20); // V2 <- (expand) V0(high) + z_vupllb(Z_V23, Z_V20); // V3 <- (expand) V0(low) + z_vuplhb(Z_V24, Z_V21); // V4 <- (expand) V1(high) + z_vupllb(Z_V25, Z_V21); // V5 <- (expand) V1(low) + z_vstm(Z_V22, Z_V25, 0+dst_off, Rdst); // store next 32 bytes + + src_off += min_vcnt; + dst_off += min_vcnt*2; + } else { + restore_inputs = true; + + z_lgfi(Rix, len>>log_min_vcnt); + bind(VectorLoop); + z_vlm(Z_V20, Z_V21, 0, Rsrc); // get next 32 characters (single-byte) + add2reg(Rsrc, min_vcnt); + + z_vuplhb(Z_V22, Z_V20); // V2 <- (expand) V0(high) + z_vupllb(Z_V23, Z_V20); // V3 <- (expand) V0(low) + z_vuplhb(Z_V24, Z_V21); // V4 <- (expand) V1(high) + z_vupllb(Z_V25, Z_V21); // V5 <- (expand) V1(low) + z_vstm(Z_V22, Z_V25, 0, Rdst); // store next 32 bytes + add2reg(Rdst, min_vcnt*2); + + z_brct(Rix, VectorLoop); + } + } + + if (((len-nprocessed) >= 16) && VM_Version::has_VectorFacility()) { + const int min_vcnt = 16; // Minimum #characters required to use vector instructions. + // Otherwise just do nothing in vector mode. + // Must be multiple of vector register length (16 bytes = 128 bits). + const int log_min_vcnt = exact_log2(min_vcnt); + const int iterations = (len - nprocessed) >> log_min_vcnt; + nprocessed += iterations << log_min_vcnt; + assert(iterations == 1, "must be!"); + + z_vl(Z_V20, 0+src_off, Z_R0, Rsrc); // get next 16 characters (single-byte) + z_vuplhb(Z_V22, Z_V20); // V2 <- (expand) V0(high) + z_vupllb(Z_V23, Z_V20); // V3 <- (expand) V0(low) + z_vstm(Z_V22, Z_V23, 0+dst_off, Rdst); // store next 32 bytes + + src_off += min_vcnt; + dst_off += min_vcnt*2; + } + + if ((len-nprocessed) > 8) { + const int min_cnt = 8; // Minimum #characters required to use unrolled scalar loop. + // Otherwise just do nothing in unrolled scalar mode. + // Must be multiple of 8. + const int log_min_cnt = exact_log2(min_cnt); + const int iterations = (len - nprocessed) >> log_min_cnt; + nprocessed += iterations << log_min_cnt; + + //---< avoid loop overhead/ptr increment for small # iterations >--- + if (iterations <= 2) { + clear_reg(Z_R0); + clear_reg(Z_R1); + workreg_clear = true; + + z_icmh(Z_R0, 5, 0+src_off, Rsrc); + z_icmh(Z_R1, 5, 4+src_off, Rsrc); + z_icm(Z_R0, 5, 2+src_off, Rsrc); + z_icm(Z_R1, 5, 6+src_off, Rsrc); + z_stmg(Z_R0, Z_R1, 0+dst_off, Rdst); + + src_off += min_cnt; + dst_off += min_cnt*2; + } + + if (iterations == 2) { + z_icmh(Z_R0, 5, 0+src_off, Rsrc); + z_icmh(Z_R1, 5, 4+src_off, Rsrc); + z_icm(Z_R0, 5, 2+src_off, Rsrc); + z_icm(Z_R1, 5, 6+src_off, Rsrc); + z_stmg(Z_R0, Z_R1, 0+dst_off, Rdst); + + src_off += min_cnt; + dst_off += min_cnt*2; + } + + if (iterations > 2) { + Label UnrolledLoop; + restore_inputs = true; + + clear_reg(Z_R0); + clear_reg(Z_R1); + workreg_clear = true; + + z_lgfi(Rix, iterations); + bind(UnrolledLoop); + z_icmh(Z_R0, 5, 0, Rsrc); + z_icmh(Z_R1, 5, 4, Rsrc); + z_icm(Z_R0, 5, 2, Rsrc); + z_icm(Z_R1, 5, 6, Rsrc); + add2reg(Rsrc, min_cnt); + + z_stmg(Z_R0, Z_R1, 0, Rdst); + add2reg(Rdst, min_cnt*2); + + z_brct(Rix, UnrolledLoop); + } + } + + if ((len-nprocessed) > 0) { + switch (len-nprocessed) { + case 8: + if (!workreg_clear) { + clear_reg(Z_R0); + clear_reg(Z_R1); + } + z_icmh(Z_R0, 5, 0+src_off, Rsrc); + z_icmh(Z_R1, 5, 4+src_off, Rsrc); + z_icm(Z_R0, 5, 2+src_off, Rsrc); + z_icm(Z_R1, 5, 6+src_off, Rsrc); + z_stmg(Z_R0, Z_R1, 0+dst_off, Rdst); + break; + case 7: + if (!workreg_clear) { + clear_reg(Z_R0); + clear_reg(Z_R1); + } + clear_reg(Rix); + z_icm(Z_R0, 5, 0+src_off, Rsrc); + z_icm(Z_R1, 5, 2+src_off, Rsrc); + z_icm(Rix, 5, 4+src_off, Rsrc); + z_stm(Z_R0, Z_R1, 0+dst_off, Rdst); + z_llc(Z_R0, 6+src_off, Z_R0, Rsrc); + z_st(Rix, 8+dst_off, Z_R0, Rdst); + z_sth(Z_R0, 12+dst_off, Z_R0, Rdst); + break; + case 6: + if (!workreg_clear) { + clear_reg(Z_R0); + clear_reg(Z_R1); + } + clear_reg(Rix); + z_icm(Z_R0, 5, 0+src_off, Rsrc); + z_icm(Z_R1, 5, 2+src_off, Rsrc); + z_icm(Rix, 5, 4+src_off, Rsrc); + z_stm(Z_R0, Z_R1, 0+dst_off, Rdst); + z_st(Rix, 8+dst_off, Z_R0, Rdst); + break; + case 5: + if (!workreg_clear) { + clear_reg(Z_R0); + clear_reg(Z_R1); + } + z_icm(Z_R0, 5, 0+src_off, Rsrc); + z_icm(Z_R1, 5, 2+src_off, Rsrc); + z_llc(Rix, 4+src_off, Z_R0, Rsrc); + z_stm(Z_R0, Z_R1, 0+dst_off, Rdst); + z_sth(Rix, 8+dst_off, Z_R0, Rdst); + break; + case 4: + if (!workreg_clear) { + clear_reg(Z_R0); + clear_reg(Z_R1); + } + z_icm(Z_R0, 5, 0+src_off, Rsrc); + z_icm(Z_R1, 5, 2+src_off, Rsrc); + z_stm(Z_R0, Z_R1, 0+dst_off, Rdst); + break; + case 3: + if (!workreg_clear) { + clear_reg(Z_R0); + } + z_llc(Z_R1, 2+src_off, Z_R0, Rsrc); + z_icm(Z_R0, 5, 0+src_off, Rsrc); + z_sth(Z_R1, 4+dst_off, Z_R0, Rdst); + z_st(Z_R0, 0+dst_off, Rdst); + break; + case 2: + z_llc(Z_R0, 0+src_off, Z_R0, Rsrc); + z_llc(Z_R1, 1+src_off, Z_R0, Rsrc); + z_sth(Z_R0, 0+dst_off, Z_R0, Rdst); + z_sth(Z_R1, 2+dst_off, Z_R0, Rdst); + break; + case 1: + z_llc(Z_R0, 0+src_off, Z_R0, Rsrc); + z_sth(Z_R0, 0+dst_off, Z_R0, Rdst); + break; + default: + guarantee(false, "Impossible"); + break; + } + src_off += len-nprocessed; + dst_off += (len-nprocessed)*2; + nprocessed = len; + } + + //---< restore modified input registers >--- + if ((nprocessed > 0) && restore_inputs) { + z_agfi(Rsrc, -(nprocessed-src_off)); + if (nprocessed < 1000000000) { // avoid int overflow + z_agfi(Rdst, -(nprocessed*2-dst_off)); + } else { + z_agfi(Rdst, -(nprocessed-dst_off)); + z_agfi(Rdst, -nprocessed); + } + } + + BLOCK_COMMENT("} string_inflate_const"); return offset() - block_start; } diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index 908ce8d98aa..8fb0731747d 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -198,6 +198,9 @@ class MacroAssembler: public Assembler { // Test a bit in a register. Result is reflected in CC. void testbit(Register r, unsigned int bitPos); + void prefetch_read(Address a); + void prefetch_update(Address a); + // Clear a register, i.e. load const zero into reg. Return len (in bytes) of // generated instruction(s). // whole_reg: Clear 64 bits if true, 32 bits otherwise. @@ -836,7 +839,7 @@ class MacroAssembler: public Assembler { void load_mirror(Register mirror, Register method); //-------------------------- - //--- perations on arrays. + //--- Operations on arrays. //-------------------------- unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len); unsigned int Clear_Array_Const(long cnt, Register base); @@ -849,20 +852,34 @@ class MacroAssembler: public Assembler { // Special String Intrinsics Implementation. //------------------------------------------- // Intrinsics for CompactStrings - // Compress char[] to byte[]. odd_reg contains cnt. tmp3 is only needed for precise behavior in failure case. Kills dst. - unsigned int string_compress(Register result, Register src, Register dst, Register odd_reg, - Register even_reg, Register tmp, Register tmp2 = noreg); + // Restores: src, dst + // Uses: cnt + // Kills: tmp, Z_R0, Z_R1. + // Early clobber: result. + // Boolean precise controls accuracy of result value. + unsigned int string_compress(Register result, Register src, Register dst, Register cnt, + Register tmp, bool precise); + + // Inflate byte[] to char[]. + unsigned int string_inflate_trot(Register src, Register dst, Register cnt, Register tmp); + + // Inflate byte[] to char[]. + // Restores: src, dst + // Uses: cnt + // Kills: tmp, Z_R0, Z_R1. + unsigned int string_inflate(Register src, Register dst, Register cnt, Register tmp); + + // Inflate byte[] to char[], length known at compile time. + // Restores: src, dst + // Kills: tmp, Z_R0, Z_R1. + // Note: + // len is signed int. Counts # characters, not bytes. + unsigned int string_inflate_const(Register src, Register dst, Register tmp, int len); // Kills src. unsigned int has_negatives(Register result, Register src, Register cnt, Register odd_reg, Register even_reg, Register tmp); - // Inflate byte[] to char[]. - unsigned int string_inflate_trot(Register src, Register dst, Register cnt, Register tmp); - // Odd_reg contains cnt. Kills src. - unsigned int string_inflate(Register src, Register dst, Register odd_reg, - Register even_reg, Register tmp); - unsigned int string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register odd_reg, Register even_reg, Register result, int ae); diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 15902d9f7aa..fb876ba6180 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -10267,14 +10267,14 @@ instruct indexOf_UL(iRegP haystack, rarg2RegI haycnt, iRegP needle, rarg5RegI ne %} // char[] to byte[] compression -instruct string_compress(iRegP src, rarg5RegP dst, iRegI result, roddRegI len, revenRegI evenReg, iRegI tmp, flagsReg cr) %{ +instruct string_compress(iRegP src, iRegP dst, iRegI result, iRegI len, iRegI tmp, flagsReg cr) %{ match(Set result (StrCompressedCopy src (Binary dst len))); - effect(TEMP_DEF result, USE_KILL dst, USE_KILL len, TEMP evenReg, TEMP tmp, KILL cr); // R0, R1 are killed, too. + effect(TEMP_DEF result, TEMP tmp, KILL cr); // R0, R1 are killed, too. ins_cost(300); format %{ "String Compress $src->$dst($len) -> $result" %} ins_encode %{ __ string_compress($result$$Register, $src$$Register, $dst$$Register, $len$$Register, - $evenReg$$Register, $tmp$$Register); + $tmp$$Register, false); %} ins_pipe(pipe_class_dummy); %} @@ -10293,13 +10293,25 @@ instruct string_compress(iRegP src, rarg5RegP dst, iRegI result, roddRegI len, r //%} // byte[] to char[] inflation -instruct string_inflate(Universe dummy, rarg5RegP src, iRegP dst, roddRegI len, revenRegI evenReg, iRegI tmp, flagsReg cr) %{ +instruct string_inflate(Universe dummy, iRegP src, iRegP dst, iRegI len, iRegI tmp, flagsReg cr) %{ match(Set dummy (StrInflatedCopy src (Binary dst len))); - effect(USE_KILL src, USE_KILL len, TEMP evenReg, TEMP tmp, KILL cr); // R0, R1 are killed, too. + effect(TEMP tmp, KILL cr); // R0, R1 are killed, too. ins_cost(300); format %{ "String Inflate $src->$dst($len)" %} ins_encode %{ - __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $evenReg$$Register, $tmp$$Register); + __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register); + %} + ins_pipe(pipe_class_dummy); +%} + +// byte[] to char[] inflation +instruct string_inflate_const(Universe dummy, iRegP src, iRegP dst, iRegI tmp, immI len, flagsReg cr) %{ + match(Set dummy (StrInflatedCopy src (Binary dst len))); + effect(TEMP tmp, KILL cr); // R0, R1 are killed, too. + ins_cost(300); + format %{ "String Inflate (constLen) $src->$dst($len)" %} + ins_encode %{ + __ string_inflate_const($src$$Register, $dst$$Register, $tmp$$Register, $len$$constant); %} ins_pipe(pipe_class_dummy); %} @@ -10318,14 +10330,14 @@ instruct has_negatives(rarg5RegP ary1, iRegI len, iRegI result, roddRegI oddReg, %} // encode char[] to byte[] in ISO_8859_1 -instruct encode_iso_array(rarg5RegP src, iRegP dst, iRegI result, roddRegI len, revenRegI evenReg, iRegI tmp, iRegI tmp2, flagsReg cr) %{ +instruct encode_iso_array(iRegP src, iRegP dst, iRegI result, iRegI len, iRegI tmp, flagsReg cr) %{ match(Set result (EncodeISOArray src (Binary dst len))); - effect(TEMP_DEF result, USE_KILL src, USE_KILL len, TEMP evenReg, TEMP tmp, TEMP tmp2, KILL cr); // R0, R1 are killed, too. + effect(TEMP_DEF result, TEMP tmp, KILL cr); // R0, R1 are killed, too. ins_cost(300); format %{ "Encode array $src->$dst($len) -> $result" %} ins_encode %{ __ string_compress($result$$Register, $src$$Register, $dst$$Register, $len$$Register, - $evenReg$$Register, $tmp$$Register, $tmp2$$Register); + $tmp$$Register, true); %} ins_pipe(pipe_class_dummy); %} diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp index 7c1e458b9d6..972bb7d9c59 100644 --- a/src/hotspot/cpu/s390/templateTable_s390.cpp +++ b/src/hotspot/cpu/s390/templateTable_s390.cpp @@ -2884,12 +2884,12 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr // ztos BTB_BEGIN(is_Bool, bsize, "putfield_or_static:is_Bool"); __ pop(ztos); - if (do_rewrite) { + if (!is_static) { pop_and_check_object(obj); } __ z_nilf(Z_tos, 0x1); __ z_stc(Z_tos, field); - if (!is_static) { + if (do_rewrite) { patch_bytecode(Bytecodes::_fast_zputfield, bc, Z_ARG5, true, byte_no); } __ z_bru(Done); diff --git a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp index 1f3dc374cce..c9b250eb06f 100644 --- a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp +++ b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp @@ -398,8 +398,13 @@ void LIR_Assembler::jobject2reg(jobject o, Register reg) { if (o == NULL) { __ set(NULL_WORD, reg); } else { +#ifdef ASSERT + { + ThreadInVMfromNative tiv(JavaThread::current()); + assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(o)), "should be real oop"); + } +#endif int oop_index = __ oop_recorder()->find_index(o); - assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(o)), "should be real oop"); RelocationHolder rspec = oop_Relocation::spec(oop_index); __ set(NULL_WORD, reg, rspec); // Will be set when the nmethod is created } diff --git a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp index 351555dbe51..d93b294574b 100644 --- a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp +++ b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp @@ -898,7 +898,9 @@ class StubGenerator: public StubCodeGenerator { assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); assert_different_registers(addr, count, tmp); - Label L_loop; + Label L_loop, L_done; + + __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_done); // zero count - nothing to do __ sll_ptr(count, LogBytesPerHeapOop, count); __ sub(count, BytesPerHeapOop, count); @@ -914,6 +916,7 @@ class StubGenerator: public StubCodeGenerator { __ subcc(count, 1, count); __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); __ delayed()->add(addr, 1, addr); + __ BIND(L_done); } break; case BarrierSet::ModRef: diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 3bdc0ed3c30..961ebb531be 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -1256,7 +1256,7 @@ void Assembler::addr_nop_8() { void Assembler::addsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x58); @@ -1266,7 +1266,7 @@ void Assembler::addsd(XMMRegister dst, XMMRegister src) { void Assembler::addsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -1276,7 +1276,7 @@ void Assembler::addsd(XMMRegister dst, Address src) { void Assembler::addss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x58); emit_int8((unsigned char)(0xC0 | encode)); @@ -1285,7 +1285,7 @@ void Assembler::addss(XMMRegister dst, XMMRegister src) { void Assembler::addss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x58); @@ -1295,7 +1295,7 @@ void Assembler::addss(XMMRegister dst, Address src) { void Assembler::aesdec(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDE); emit_operand(dst, src); @@ -1303,7 +1303,7 @@ void Assembler::aesdec(XMMRegister dst, Address src) { void Assembler::aesdec(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDE); emit_int8(0xC0 | encode); @@ -1312,7 +1312,7 @@ void Assembler::aesdec(XMMRegister dst, XMMRegister src) { void Assembler::aesdeclast(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDF); emit_operand(dst, src); @@ -1320,7 +1320,7 @@ void Assembler::aesdeclast(XMMRegister dst, Address src) { void Assembler::aesdeclast(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDF); emit_int8((unsigned char)(0xC0 | encode)); @@ -1329,7 +1329,7 @@ void Assembler::aesdeclast(XMMRegister dst, XMMRegister src) { void Assembler::aesenc(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDC); emit_operand(dst, src); @@ -1337,7 +1337,7 @@ void Assembler::aesenc(XMMRegister dst, Address src) { void Assembler::aesenc(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDC); emit_int8(0xC0 | encode); @@ -1346,7 +1346,7 @@ void Assembler::aesenc(XMMRegister dst, XMMRegister src) { void Assembler::aesenclast(XMMRegister dst, Address src) { assert(VM_Version::supports_aes(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDD); emit_operand(dst, src); @@ -1354,7 +1354,7 @@ void Assembler::aesenclast(XMMRegister dst, Address src) { void Assembler::aesenclast(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_aes(), ""); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xDD); emit_int8((unsigned char)(0xC0 | encode)); @@ -1387,7 +1387,7 @@ void Assembler::andl(Register dst, Register src) { void Assembler::andnl(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF2); emit_int8((unsigned char)(0xC0 | encode)); @@ -1396,7 +1396,7 @@ void Assembler::andnl(Register dst, Register src1, Register src2) { void Assembler::andnl(Register dst, Register src1, Address src2) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src2, src1->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF2); emit_operand(dst, src2); @@ -1424,7 +1424,7 @@ void Assembler::bswapl(Register reg) { // bswap void Assembler::blsil(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(rbx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); @@ -1433,7 +1433,7 @@ void Assembler::blsil(Register dst, Register src) { void Assembler::blsil(Register dst, Address src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src, dst->encoding(), rbx->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_operand(rbx, src); @@ -1441,7 +1441,7 @@ void Assembler::blsil(Register dst, Address src) { void Assembler::blsmskl(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(rdx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); @@ -1450,7 +1450,7 @@ void Assembler::blsmskl(Register dst, Register src) { void Assembler::blsmskl(Register dst, Address src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src, dst->encoding(), rdx->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_operand(rdx, src); @@ -1458,7 +1458,7 @@ void Assembler::blsmskl(Register dst, Address src) { void Assembler::blsrl(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(rcx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); @@ -1467,7 +1467,7 @@ void Assembler::blsrl(Register dst, Register src) { void Assembler::blsrl(Register dst, Address src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src, dst->encoding(), rcx->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_operand(rcx, src); @@ -1753,7 +1753,7 @@ void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) { void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x5A); @@ -1763,7 +1763,7 @@ void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { void Assembler::cvtsd2ss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -1817,7 +1817,7 @@ void Assembler::cvtsi2ssq(XMMRegister dst, Register src) { void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5A); emit_int8((unsigned char)(0xC0 | encode)); @@ -1826,7 +1826,7 @@ void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) { void Assembler::cvtss2sd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5A); @@ -1870,7 +1870,7 @@ void Assembler::decl(Address dst) { void Assembler::divsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -1880,7 +1880,7 @@ void Assembler::divsd(XMMRegister dst, Address src) { void Assembler::divsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x5E); @@ -1890,7 +1890,7 @@ void Assembler::divsd(XMMRegister dst, XMMRegister src) { void Assembler::divss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5E); @@ -1899,7 +1899,7 @@ void Assembler::divss(XMMRegister dst, Address src) { void Assembler::divss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5E); emit_int8((unsigned char)(0xC0 | encode)); @@ -2105,7 +2105,7 @@ void Assembler::jmpb(Label& L) { void Assembler::ldmxcsr( Address src) { if (UseAVX > 0 ) { InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); emit_int8((unsigned char)0xAE); emit_operand(as_Register(2), src); @@ -2784,7 +2784,7 @@ void Assembler::movsbl(Register dst, Register src) { // movsxb void Assembler::movsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x10); @@ -2794,7 +2794,7 @@ void Assembler::movsd(XMMRegister dst, XMMRegister src) { void Assembler::movsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -2805,7 +2805,7 @@ void Assembler::movsd(XMMRegister dst, Address src) { void Assembler::movsd(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.reset_is_clear_context(); attributes.set_rex_vex_w_reverted(); @@ -2816,7 +2816,7 @@ void Assembler::movsd(Address dst, XMMRegister src) { void Assembler::movss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x10); emit_int8((unsigned char)(0xC0 | encode)); @@ -2825,7 +2825,7 @@ void Assembler::movss(XMMRegister dst, XMMRegister src) { void Assembler::movss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); simd_prefix(dst, xnoreg, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x10); @@ -2835,7 +2835,7 @@ void Assembler::movss(XMMRegister dst, Address src) { void Assembler::movss(Address dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); attributes.reset_is_clear_context(); simd_prefix(src, xnoreg, dst, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); @@ -2931,7 +2931,7 @@ void Assembler::mull(Register src) { void Assembler::mulsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -2941,7 +2941,7 @@ void Assembler::mulsd(XMMRegister dst, Address src) { void Assembler::mulsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x59); @@ -2951,7 +2951,7 @@ void Assembler::mulsd(XMMRegister dst, XMMRegister src) { void Assembler::mulss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x59); @@ -2960,7 +2960,7 @@ void Assembler::mulss(XMMRegister dst, Address src) { void Assembler::mulss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x59); emit_int8((unsigned char)(0xC0 | encode)); @@ -4289,7 +4289,7 @@ void Assembler::vpalignr(XMMRegister dst, XMMRegister nds, XMMRegister src, int void Assembler::pblendw(XMMRegister dst, XMMRegister src, int imm8) { assert(VM_Version::supports_sse4_1(), ""); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8((unsigned char)0x0E); emit_int8((unsigned char)(0xC0 | encode)); @@ -4388,7 +4388,7 @@ void Assembler::smovl() { void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x51); @@ -4398,7 +4398,7 @@ void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { void Assembler::sqrtsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -4408,7 +4408,7 @@ void Assembler::sqrtsd(XMMRegister dst, Address src) { void Assembler::sqrtss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x51); emit_int8((unsigned char)(0xC0 | encode)); @@ -4421,7 +4421,7 @@ void Assembler::std() { void Assembler::sqrtss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x51); @@ -4484,7 +4484,7 @@ void Assembler::subl(Register dst, Register src) { void Assembler::subsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x5C); @@ -4494,7 +4494,7 @@ void Assembler::subsd(XMMRegister dst, XMMRegister src) { void Assembler::subsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -4504,7 +4504,7 @@ void Assembler::subsd(XMMRegister dst, Address src) { void Assembler::subss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false , /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true , /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5C); emit_int8((unsigned char)(0xC0 | encode)); @@ -4513,7 +4513,7 @@ void Assembler::subss(XMMRegister dst, XMMRegister src) { void Assembler::subss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5C); @@ -4735,7 +4735,7 @@ void Assembler::xorb(Register dst, Address src) { void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -4745,7 +4745,7 @@ void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x58); @@ -4755,7 +4755,7 @@ void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { void Assembler::vaddss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x58); @@ -4764,7 +4764,7 @@ void Assembler::vaddss(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x58); emit_int8((unsigned char)(0xC0 | encode)); @@ -4773,7 +4773,7 @@ void Assembler::vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src) { void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -4783,7 +4783,7 @@ void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x5E); @@ -4793,7 +4793,7 @@ void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { void Assembler::vdivss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5E); @@ -4802,7 +4802,7 @@ void Assembler::vdivss(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5E); emit_int8((unsigned char)(0xC0 | encode)); @@ -4810,7 +4810,7 @@ void Assembler::vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) { void Assembler::vfmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { assert(VM_Version::supports_fma(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xB9); emit_int8((unsigned char)(0xC0 | encode)); @@ -4818,7 +4818,7 @@ void Assembler::vfmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) void Assembler::vfmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { assert(VM_Version::supports_fma(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xB9); emit_int8((unsigned char)(0xC0 | encode)); @@ -4827,7 +4827,7 @@ void Assembler::vfmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -4837,7 +4837,7 @@ void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x59); @@ -4847,7 +4847,7 @@ void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { void Assembler::vmulss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x59); @@ -4856,7 +4856,7 @@ void Assembler::vmulss(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vmulss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x59); emit_int8((unsigned char)(0xC0 | encode)); @@ -4865,7 +4865,7 @@ void Assembler::vmulss(XMMRegister dst, XMMRegister nds, XMMRegister src) { void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); attributes.set_rex_vex_w_reverted(); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); @@ -4875,7 +4875,7 @@ void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_rex_vex_w_reverted(); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); emit_int8(0x5C); @@ -4885,7 +4885,7 @@ void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { void Assembler::vsubss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5C); @@ -4894,7 +4894,7 @@ void Assembler::vsubss(XMMRegister dst, XMMRegister nds, Address src) { void Assembler::vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); emit_int8(0x5C); emit_int8((unsigned char)(0xC0 | encode)); @@ -5203,6 +5203,24 @@ void Assembler::vsqrtpd(XMMRegister dst, Address src, int vector_len) { emit_operand(dst, src); } +void Assembler::vsqrtps(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8(0x51); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vsqrtps(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_avx(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8(0x51); + emit_operand(dst, src); +} + void Assembler::andpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ !_legacy_mode_dq, /* legacy_mode */ _legacy_mode_dq, /* no_mask_reg */ false, /* uses_vl */ true); @@ -5377,7 +5395,7 @@ void Assembler::vxorps(XMMRegister dst, XMMRegister nds, Address src, int vector void Assembler::vphaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx() && (vector_len == 0) || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); - InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8(0x01); emit_int8((unsigned char)(0xC0 | encode)); @@ -5436,7 +5454,7 @@ void Assembler::paddq(XMMRegister dst, XMMRegister src) { void Assembler::phaddw(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_sse3(), ""); - InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8(0x01); emit_int8((unsigned char)(0xC0 | encode)); @@ -6679,7 +6697,7 @@ void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, in void Assembler::vzeroupper() { if (VM_Version::supports_vzeroupper()) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); (void)vex_prefix_and_encode(0, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); emit_int8(0x77); } @@ -7442,7 +7460,7 @@ void Assembler::vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src, int void Assembler::shlxl(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); emit_int8((unsigned char)(0xC0 | encode)); @@ -7450,7 +7468,7 @@ void Assembler::shlxl(Register dst, Register src1, Register src2) { void Assembler::shlxq(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src1->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF7); emit_int8((unsigned char)(0xC0 | encode)); @@ -7985,7 +8003,7 @@ void Assembler::andq(Register dst, Register src) { void Assembler::andnq(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF2); emit_int8((unsigned char)(0xC0 | encode)); @@ -7994,7 +8012,7 @@ void Assembler::andnq(Register dst, Register src1, Register src2) { void Assembler::andnq(Register dst, Register src1, Address src2) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src2, src1->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF2); emit_operand(dst, src2); @@ -8022,7 +8040,7 @@ void Assembler::bswapq(Register reg) { void Assembler::blsiq(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(rbx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); @@ -8031,7 +8049,7 @@ void Assembler::blsiq(Register dst, Register src) { void Assembler::blsiq(Register dst, Address src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src, dst->encoding(), rbx->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_operand(rbx, src); @@ -8039,7 +8057,7 @@ void Assembler::blsiq(Register dst, Address src) { void Assembler::blsmskq(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(rdx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); @@ -8048,7 +8066,7 @@ void Assembler::blsmskq(Register dst, Register src) { void Assembler::blsmskq(Register dst, Address src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src, dst->encoding(), rdx->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_operand(rdx, src); @@ -8056,7 +8074,7 @@ void Assembler::blsmskq(Register dst, Address src) { void Assembler::blsrq(Register dst, Register src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(rcx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_int8((unsigned char)(0xC0 | encode)); @@ -8065,7 +8083,7 @@ void Assembler::blsrq(Register dst, Register src) { void Assembler::blsrq(Register dst, Address src) { assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); InstructionMark im(this); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); vex_prefix(src, dst->encoding(), rcx->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF3); emit_operand(rcx, src); @@ -8504,7 +8522,7 @@ void Assembler::mulq(Register src) { void Assembler::mulxq(Register dst1, Register dst2, Register src) { assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst1->encoding(), dst2->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, &attributes); emit_int8((unsigned char)0xF6); emit_int8((unsigned char)(0xC0 | encode)); @@ -8667,7 +8685,7 @@ void Assembler::rorq(Register dst, int imm8) { void Assembler::rorxq(Register dst, Register src, int imm8) { assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_3A, &attributes); emit_int8((unsigned char)0xF0); emit_int8((unsigned char)(0xC0 | encode)); @@ -8676,7 +8694,7 @@ void Assembler::rorxq(Register dst, Register src, int imm8) { void Assembler::rorxd(Register dst, Register src, int imm8) { assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported"); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_3A, &attributes); emit_int8((unsigned char)0xF0); emit_int8((unsigned char)(0xC0 | encode)); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index c4e6645e319..2739cf3b5eb 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1919,9 +1919,11 @@ private: void vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); void vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len); - // Sqrt Packed Floating-Point Values - Double precision only + // Sqrt Packed Floating-Point Values void vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len); void vsqrtpd(XMMRegister dst, Address src, int vector_len); + void vsqrtps(XMMRegister dst, XMMRegister src, int vector_len); + void vsqrtps(XMMRegister dst, Address src, int vector_len); // Bitwise Logical AND of Packed Floating-Point Values void andpd(XMMRegister dst, XMMRegister src); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 3ac35d752e4..112321cce78 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -6630,6 +6630,13 @@ void MacroAssembler::restore_cpu_control_state_after_jni() { } // Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty. vzeroupper(); + // Reset k1 to 0xffff. + if (VM_Version::supports_evex()) { + push(rcx); + movl(rcx, 0xffff); + kmovwl(k1, rcx); + pop(rcx); + } #ifndef _LP64 // Either restore the x87 floating pointer control word after returning diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index cf85d5807a2..3f0d57bcce0 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -3388,26 +3388,29 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t // No exception case __ bind(noException); - Label no_adjust, bail; + Label no_adjust, bail, no_prefix; if (SafepointMechanism::uses_thread_local_poll() && !cause_return) { // If our stashed return pc was modified by the runtime we avoid touching it __ cmpptr(rbx, Address(rbp, wordSize)); __ jccb(Assembler::notEqual, no_adjust); -#ifdef ASSERT // Verify the correct encoding of the poll we're about to skip. // See NativeInstruction::is_safepoint_poll() __ cmpb(Address(rbx, 0), NativeTstRegMem::instruction_rex_b_prefix); - __ jcc(Assembler::notEqual, bail); - __ cmpb(Address(rbx, 1), NativeTstRegMem::instruction_code_memXregl); + __ jcc(Assembler::notEqual, no_prefix); + __ addptr(rbx, 1); + __ bind(no_prefix); +#ifdef ASSERT + __ cmpb(Address(rbx, 0), NativeTstRegMem::instruction_code_memXregl); __ jcc(Assembler::notEqual, bail); // Mask out the modrm bits - __ testb(Address(rbx, 2), NativeTstRegMem::modrm_mask); + __ testb(Address(rbx, 1), NativeTstRegMem::modrm_mask); // rax encodes to 0, so if the bits are nonzero it's incorrect __ jcc(Assembler::notZero, bail); #endif // Adjust return pc forward to step over the safepoint poll instruction - __ addptr(Address(rbp, wordSize), 3); + __ addptr(rbx, 2); + __ movptr(Address(rbp, wordSize), rbx); } __ bind(no_adjust); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 7db8ba32981..5b28a4e28d5 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -1264,9 +1264,12 @@ class StubGenerator: public StubCodeGenerator { CardTableModRefBS* ct = barrier_set_cast(bs); assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - Label L_loop; + Label L_loop, L_done; const Register end = count; + __ testl(count, count); + __ jcc(Assembler::zero, L_done); // zero count - nothing to do + __ leaq(end, Address(start, count, TIMES_OOP, 0)); // end == start+count*oop_size __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive __ shrptr(start, CardTableModRefBS::card_shift); @@ -1280,6 +1283,7 @@ class StubGenerator: public StubCodeGenerator { __ movb(Address(start, count, Address::times_1), 0); __ decrement(count); __ jcc(Assembler::greaterEqual, L_loop); + __ BIND(L_done); } break; default: diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index f322d60a6ed..563ff1f111b 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -629,18 +629,26 @@ void VM_Version::get_processor_features() { _features &= ~CPU_SSE; // first try initial setting and detect what we can support + int use_avx_limit = 0; if (UseAVX > 0) { if (UseAVX > 2 && supports_evex()) { - UseAVX = 3; + use_avx_limit = 3; } else if (UseAVX > 1 && supports_avx2()) { - UseAVX = 2; + use_avx_limit = 2; } else if (UseAVX > 0 && supports_avx()) { - UseAVX = 1; + use_avx_limit = 1; } else { - UseAVX = 0; + use_avx_limit = 0; } + } + if (FLAG_IS_DEFAULT(UseAVX)) { + FLAG_SET_DEFAULT(UseAVX, use_avx_limit); + } else if (UseAVX > use_avx_limit) { + warning("UseAVX=%d is not supported on this CPU, setting it to UseAVX=%d", (int) UseAVX, use_avx_limit); + FLAG_SET_DEFAULT(UseAVX, use_avx_limit); } else if (UseAVX < 0) { - UseAVX = 0; + warning("UseAVX=%d is not valid, setting it to UseAVX=0", (int) UseAVX); + FLAG_SET_DEFAULT(UseAVX, 0); } if (UseAVX < 3) { @@ -710,16 +718,29 @@ void VM_Version::get_processor_features() { // UseSSE is set to the smaller of what hardware supports and what // the command line requires. I.e., you cannot set UseSSE to 2 on // older Pentiums which do not support it. - if (UseSSE > 4) UseSSE=4; - if (UseSSE < 0) UseSSE=0; - if (!supports_sse4_1()) // Drop to 3 if no SSE4 support - UseSSE = MIN2((intx)3,UseSSE); - if (!supports_sse3()) // Drop to 2 if no SSE3 support - UseSSE = MIN2((intx)2,UseSSE); - if (!supports_sse2()) // Drop to 1 if no SSE2 support - UseSSE = MIN2((intx)1,UseSSE); - if (!supports_sse ()) // Drop to 0 if no SSE support - UseSSE = 0; + int use_sse_limit = 0; + if (UseSSE > 0) { + if (UseSSE > 3 && supports_sse4_1()) { + use_sse_limit = 4; + } else if (UseSSE > 2 && supports_sse3()) { + use_sse_limit = 3; + } else if (UseSSE > 1 && supports_sse2()) { + use_sse_limit = 2; + } else if (UseSSE > 0 && supports_sse()) { + use_sse_limit = 1; + } else { + use_sse_limit = 0; + } + } + if (FLAG_IS_DEFAULT(UseSSE)) { + FLAG_SET_DEFAULT(UseSSE, use_sse_limit); + } else if (UseSSE > use_sse_limit) { + warning("UseSSE=%d is not supported on this CPU, setting it to UseSSE=%d", (int) UseSSE, use_sse_limit); + FLAG_SET_DEFAULT(UseSSE, use_sse_limit); + } else if (UseSSE < 0) { + warning("UseSSE=%d is not valid, setting it to UseSSE=0", (int) UseSSE); + FLAG_SET_DEFAULT(UseSSE, 0); + } // Use AES instructions if available. if (supports_aes()) { diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index afaa2da23c7..124e95a4dcd 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1252,6 +1252,7 @@ const bool Matcher::match_rule_supported(int opcode) { ret_value = false; break; case Op_SqrtVD: + case Op_SqrtVF: if (UseAVX < 1) // enabled for AVX only ret_value = false; break; @@ -2580,7 +2581,7 @@ instruct negD_reg_reg(regD dst, regD src) %{ instruct sqrtF_reg(regF dst, regF src) %{ predicate(UseSSE>=1); - match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); + match(Set dst (SqrtF src)); format %{ "sqrtss $dst, $src" %} ins_cost(150); @@ -2592,7 +2593,7 @@ instruct sqrtF_reg(regF dst, regF src) %{ instruct sqrtF_mem(regF dst, memory src) %{ predicate(UseSSE>=1); - match(Set dst (ConvD2F (SqrtD (ConvF2D (LoadF src))))); + match(Set dst (SqrtF (LoadF src))); format %{ "sqrtss $dst, $src" %} ins_cost(150); @@ -2604,7 +2605,8 @@ instruct sqrtF_mem(regF dst, memory src) %{ instruct sqrtF_imm(regF dst, immF con) %{ predicate(UseSSE>=1); - match(Set dst (ConvD2F (SqrtD (ConvF2D con)))); + match(Set dst (SqrtF con)); + format %{ "sqrtss $dst, [$constantaddress]\t# load from constant table: float=$con" %} ins_cost(150); ins_encode %{ @@ -8388,7 +8390,7 @@ instruct vshiftcnt(vecS dst, rRegI cnt) %{ // --------------------------------- Sqrt -------------------------------------- -// Floating point vector sqrt - double precision only +// Floating point vector sqrt instruct vsqrt2D_reg(vecX dst, vecX src) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SqrtVD src)); @@ -8455,6 +8457,94 @@ instruct vsqrt8D_mem(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} +instruct vsqrt2F_reg(vecD dst, vecD src) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SqrtVF src)); + format %{ "vsqrtps $dst,$src\t! sqrt packed2F" %} + ins_encode %{ + int vector_len = 0; + __ vsqrtps($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsqrt2F_mem(vecD dst, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SqrtVF (LoadVector mem))); + format %{ "vsqrtps $dst,$mem\t! sqrt packed2F" %} + ins_encode %{ + int vector_len = 0; + __ vsqrtps($dst$$XMMRegister, $mem$$Address, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsqrt4F_reg(vecX dst, vecX src) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SqrtVF src)); + format %{ "vsqrtps $dst,$src\t! sqrt packed4F" %} + ins_encode %{ + int vector_len = 0; + __ vsqrtps($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsqrt4F_mem(vecX dst, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SqrtVF (LoadVector mem))); + format %{ "vsqrtps $dst,$mem\t! sqrt packed4F" %} + ins_encode %{ + int vector_len = 0; + __ vsqrtps($dst$$XMMRegister, $mem$$Address, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsqrt8F_reg(vecY dst, vecY src) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (SqrtVF src)); + format %{ "vsqrtps $dst,$src\t! sqrt packed8F" %} + ins_encode %{ + int vector_len = 1; + __ vsqrtps($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsqrt8F_mem(vecY dst, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (SqrtVF (LoadVector mem))); + format %{ "vsqrtps $dst,$mem\t! sqrt packed8F" %} + ins_encode %{ + int vector_len = 1; + __ vsqrtps($dst$$XMMRegister, $mem$$Address, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsqrt16F_reg(vecZ dst, vecZ src) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 16); + match(Set dst (SqrtVF src)); + format %{ "vsqrtps $dst,$src\t! sqrt packed16F" %} + ins_encode %{ + int vector_len = 2; + __ vsqrtps($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsqrt16F_mem(vecZ dst, memory mem) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 16); + match(Set dst (SqrtVF (LoadVector mem))); + format %{ "vsqrtps $dst,$mem\t! sqrt packed16F" %} + ins_encode %{ + int vector_len = 2; + __ vsqrtps($dst$$XMMRegister, $mem$$Address, vector_len); + %} + ins_pipe( pipe_slow ); +%} + // ------------------------------ LeftShift ----------------------------------- // Shorts/Chars vector left shift diff --git a/src/hotspot/os/aix/osThread_aix.cpp b/src/hotspot/os/aix/osThread_aix.cpp index 0b13454ffef..6303dc27eb8 100644 --- a/src/hotspot/os/aix/osThread_aix.cpp +++ b/src/hotspot/os/aix/osThread_aix.cpp @@ -25,6 +25,7 @@ // no precompiled headers +#include "memory/allocation.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index df5959b26d0..0325824e021 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -2490,6 +2490,22 @@ bool os::can_execute_large_page_memory() { return false; } +char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) { + assert(file_desc >= 0, "file_desc is not valid"); + char* result = NULL; + + // Always round to os::vm_page_size(), which may be larger than 4K. + bytes = align_up(bytes, os::vm_page_size()); + result = reserve_mmaped_memory(bytes, requested_addr, 0); + + if (result != NULL) { + if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } + } + return result; +} + // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { diff --git a/src/hotspot/os/bsd/osThread_bsd.cpp b/src/hotspot/os/bsd/osThread_bsd.cpp index de1383be848..c614f3825e3 100644 --- a/src/hotspot/os/bsd/osThread_bsd.cpp +++ b/src/hotspot/os/bsd/osThread_bsd.cpp @@ -23,6 +23,7 @@ */ // no precompiled headers +#include "memory/allocation.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/osThread.hpp" diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 6ebcb627fdc..64afc14318c 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -2350,6 +2350,17 @@ bool os::can_execute_large_page_memory() { return UseHugeTLBFS; } +char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) { + assert(file_desc >= 0, "file_desc is not valid"); + char* result = pd_attempt_reserve_memory_at(bytes, requested_addr); + if (result != NULL) { + if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } + } + return result; +} + // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index 03fd695cbc4..dacd53b27dc 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -323,7 +323,12 @@ void OSContainer::init() { } } - if (mntinfo != NULL) fclose(mntinfo); + fclose(mntinfo); + + if (memory == NULL || cpuset == NULL || cpu == NULL || cpuacct == NULL) { + log_debug(os, container)("Required cgroup subsystems not found"); + return; + } /* * Read /proc/self/cgroup and map host mount point to @@ -383,12 +388,7 @@ void OSContainer::init() { } } - if (cgroup != NULL) fclose(cgroup); - - if (memory == NULL || cpuset == NULL || cpu == NULL) { - log_debug(os, container)("Required cgroup subsystems not found"); - return; - } + fclose(cgroup); // We need to update the amount of physical memory now that // command line arguments have been processed. diff --git a/src/hotspot/os/linux/osThread_linux.cpp b/src/hotspot/os/linux/osThread_linux.cpp index 381e7b0e7ba..6f7e074a522 100644 --- a/src/hotspot/os/linux/osThread_linux.cpp +++ b/src/hotspot/os/linux/osThread_linux.cpp @@ -23,6 +23,7 @@ */ // no precompiled headers +#include "memory/allocation.inline.hpp" #include "runtime/mutex.hpp" #include "runtime/osThread.hpp" diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 548e7823f7f..a91fac1b9fe 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -59,6 +59,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/timer.hpp" #include "semaphore_posix.hpp" #include "services/attachListener.hpp" @@ -129,6 +130,7 @@ #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) #define LARGEPAGES_BIT (1 << 6) +#define DAX_SHARED_BIT (1 << 8) //////////////////////////////////////////////////////////////////////////////// // global variables julong os::Linux::_physical_memory = 0; @@ -1646,7 +1648,10 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { // // Dynamic loader will make all stacks executable after // this function returns, and will not do that again. - assert(Threads::first() == NULL, "no Java threads should exist yet."); +#ifdef ASSERT + ThreadsListHandle tlh; + assert(tlh.length() == 0, "no Java threads should exist yet."); +#endif } else { warning("You have loaded library %s which might have disabled stack guard. " "The VM will try to fix the stack guard now.\n" @@ -1874,16 +1879,13 @@ void * os::Linux::dll_load_in_vmthread(const char *filename, char *ebuf, // may have been queued at the same time. if (!_stack_is_executable) { - JavaThread *jt = Threads::first(); - - while (jt) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { if (!jt->stack_guard_zone_unused() && // Stack not yet fully initialized jt->stack_guards_enabled()) { // No pending stack overflow exceptions if (!os::guard_memory((char *)jt->stack_end(), jt->stack_guard_zone_size())) { warning("Attempt to reguard stack yellow zone failed."); } } - jt = jt->next(); } } @@ -3369,10 +3371,13 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) { // effective only if the bit 2 is cleared) // - (bit 5) hugetlb private memory // - (bit 6) hugetlb shared memory +// - (bit 7) dax private memory +// - (bit 8) dax shared memory // -static void set_coredump_filter(void) { +static void set_coredump_filter(bool largepages, bool dax_shared) { FILE *f; long cdm; + bool filter_changed = false; if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) { return; @@ -3385,8 +3390,15 @@ static void set_coredump_filter(void) { rewind(f); - if ((cdm & LARGEPAGES_BIT) == 0) { + if (largepages && (cdm & LARGEPAGES_BIT) == 0) { cdm |= LARGEPAGES_BIT; + filter_changed = true; + } + if (dax_shared && (cdm & DAX_SHARED_BIT) == 0) { + cdm |= DAX_SHARED_BIT; + filter_changed = true; + } + if (filter_changed) { fprintf(f, "%#lx", cdm); } @@ -3525,7 +3537,7 @@ void os::large_page_init() { size_t large_page_size = Linux::setup_large_page_size(); UseLargePages = Linux::setup_large_page_type(large_page_size); - set_coredump_filter(); + set_coredump_filter(true /*largepages*/, false /*dax_shared*/); } #ifndef SHM_HUGETLB @@ -3896,6 +3908,17 @@ bool os::can_execute_large_page_memory() { return UseTransparentHugePages || UseHugeTLBFS; } +char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) { + assert(file_desc >= 0, "file_desc is not valid"); + char* result = pd_attempt_reserve_memory_at(bytes, requested_addr); + if (result != NULL) { + if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } + } + return result; +} + // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). @@ -4947,25 +4970,20 @@ jint os::init_2(void) { UseNUMA = false; } } - // With SHM and HugeTLBFS large pages we cannot uncommit a page, so there's no way - // we can make the adaptive lgrp chunk resizing work. If the user specified - // both UseNUMA and UseLargePages (or UseSHM/UseHugeTLBFS) on the command line - warn and - // disable adaptive resizing. - if (UseNUMA && UseLargePages && !can_commit_large_page_memory()) { - if (FLAG_IS_DEFAULT(UseNUMA)) { - UseNUMA = false; - } else { - if (FLAG_IS_DEFAULT(UseLargePages) && - FLAG_IS_DEFAULT(UseSHM) && - FLAG_IS_DEFAULT(UseHugeTLBFS)) { - UseLargePages = false; - } else if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) { - warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)"); - UseAdaptiveSizePolicy = false; - UseAdaptiveNUMAChunkSizing = false; - } + + if (UseParallelGC && UseNUMA && UseLargePages && !can_commit_large_page_memory()) { + // With SHM and HugeTLBFS large pages we cannot uncommit a page, so there's no way + // we can make the adaptive lgrp chunk resizing work. If the user specified both + // UseNUMA and UseLargePages (or UseSHM/UseHugeTLBFS) on the command line - warn + // and disable adaptive resizing. + if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) { + warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, " + "disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)"); + UseAdaptiveSizePolicy = false; + UseAdaptiveNUMAChunkSizing = false; } } + if (!UseNUMA && ForceNUMA) { UseNUMA = true; } @@ -5012,6 +5030,9 @@ jint os::init_2(void) { // initialize thread priority policy prio_init(); + if (!FLAG_IS_DEFAULT(AllocateHeapAt)) { + set_coredump_filter(false /*largepages*/, true /*dax_shared*/); + } return JNI_OK; } diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index fed874d30eb..8c7cf351ef0 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,20 @@ #endif #define IS_VALID_PID(p) (p > 0 && p < MAX_PID) +#ifndef MAP_ANONYMOUS + #define MAP_ANONYMOUS MAP_ANON +#endif + +#define check_with_errno(check_type, cond, msg) \ + do { \ + int err = errno; \ + check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \ + os::errno_name(err)); \ +} while (false) + +#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg) +#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg) + // Check core dump limit and report possible place where core can be found void os::check_dump_limit(char* buffer, size_t bufferSize) { if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) { @@ -145,10 +160,124 @@ void os::wait_for_keypress_at_exit(void) { return; } +int os::create_file_for_heap(const char* dir) { + + const char name_template[] = "/jvmheap.XXXXXX"; + + char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal); + if (fullname == NULL) { + vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno))); + return -1; + } + (void)strncpy(fullname, dir, strlen(dir)+1); + (void)strncat(fullname, name_template, strlen(name_template)); + + os::native_path(fullname); + + sigset_t set, oldset; + int ret = sigfillset(&set); + assert_with_errno(ret == 0, "sigfillset returned error"); + + // set the file creation mask. + mode_t file_mode = S_IRUSR | S_IWUSR; + + // create a new file. + int fd = mkstemp(fullname); + + if (fd < 0) { + warning("Could not create file for heap with template %s", fullname); + os::free(fullname); + return -1; + } + + // delete the name from the filesystem. When 'fd' is closed, the file (and space) will be deleted. + ret = unlink(fullname); + assert_with_errno(ret == 0, "unlink returned error"); + + os::free(fullname); + return fd; +} + +static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) { + char * addr; + int flags = MAP_PRIVATE NOT_AIX( | MAP_NORESERVE ) | MAP_ANONYMOUS; + if (requested_addr != NULL) { + assert((uintptr_t)requested_addr % os::vm_page_size() == 0, "Requested address should be aligned to OS page size"); + flags |= MAP_FIXED; + } + + // Map reserved/uncommitted pages PROT_NONE so we fail early if we + // touch an uncommitted page. Otherwise, the read/write might + // succeed if we have enough swap space to back the physical page. + addr = (char*)::mmap(requested_addr, bytes, PROT_NONE, + flags, -1, 0); + + if (addr != MAP_FAILED) { + MemTracker::record_virtual_memory_reserve((address)addr, bytes, CALLER_PC); + return addr; + } + return NULL; +} + +static int util_posix_fallocate(int fd, off_t offset, off_t len) { +#ifdef __APPLE__ + fstore_t store = { F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, len }; + // First we try to get a continuous chunk of disk space + int ret = fcntl(fd, F_PREALLOCATE, &store); + if (ret == -1) { + // Maybe we are too fragmented, try to allocate non-continuous range + store.fst_flags = F_ALLOCATEALL; + ret = fcntl(fd, F_PREALLOCATE, &store); + } + if(ret != -1) { + return ftruncate(fd, len); + } + return -1; +#else + return posix_fallocate(fd, offset, len); +#endif +} + +// Map the given address range to the provided file descriptor. +char* os::map_memory_to_file(char* base, size_t size, int fd) { + assert(fd != -1, "File descriptor is not valid"); + + // allocate space for the file + if (util_posix_fallocate(fd, 0, (off_t)size) != 0) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory.")); + return NULL; + } + + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_SHARED; + if (base != NULL) { + flags |= MAP_FIXED; + } + char* addr = (char*)mmap(base, size, prot, flags, fd, 0); + + if (addr == MAP_FAILED) { + return NULL; + } + if (base != NULL && addr != base) { + if (!os::release_memory(addr, size)) { + warning("Could not release memory on unsuccessful file mapping"); + } + return NULL; + } + return addr; +} + +char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd) { + assert(fd != -1, "File descriptor is not valid"); + assert(base != NULL, "Base cannot be NULL"); + + return map_memory_to_file(base, size, fd); +} + // Multiple threads can race in this code, and can remap over each other with MAP_FIXED, // so on posix, unmap the section at the start and at the end of the chunk that we mapped // rather than unmapping and remapping the whole chunk to get requested alignment. -char* os::reserve_memory_aligned(size_t size, size_t alignment) { +char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { assert((alignment & (os::vm_allocation_granularity() - 1)) == 0, "Alignment must be a multiple of allocation granularity (page size)"); assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned"); @@ -156,7 +285,20 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment) { size_t extra_size = size + alignment; assert(extra_size >= size, "overflow, size is too large to allow alignment"); - char* extra_base = os::reserve_memory(extra_size, NULL, alignment); + char* extra_base; + if (file_desc != -1) { + // For file mapping, we do not call os:reserve_memory(extra_size, NULL, alignment, file_desc) because + // we need to deal with shrinking of the file space later when we release extra memory after alignment. + // We also cannot called os:reserve_memory() with file_desc set to -1 because on aix we might get SHM memory. + // So here to call a helper function while reserve memory for us. After we have a aligned base, + // we will replace anonymous mapping with file mapping. + extra_base = reserve_mmapped_memory(extra_size, NULL); + if (extra_base != NULL) { + MemTracker::record_virtual_memory_reserve((address)extra_base, extra_size, CALLER_PC); + } + } else { + extra_base = os::reserve_memory(extra_size, NULL, alignment); + } if (extra_base == NULL) { return NULL; @@ -183,6 +325,13 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment) { os::release_memory(extra_base + begin_offset + size, end_offset); } + if (file_desc != -1) { + // After we have an aligned address, we can replace anonymous mapping with file mapping + if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } + MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC); + } return aligned_base; } @@ -478,8 +627,7 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) { // interrupt support void os::interrupt(Thread* thread) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); + debug_only(Thread::check_for_dangling_thread_pointer(thread);) OSThread* osthread = thread->osthread(); @@ -499,12 +647,10 @@ void os::interrupt(Thread* thread) { ParkEvent * ev = thread->_ParkEvent ; if (ev != NULL) ev->unpark() ; - } bool os::is_interrupted(Thread* thread, bool clear_interrupted) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); + debug_only(Thread::check_for_dangling_thread_pointer(thread);) OSThread* osthread = thread->osthread(); @@ -1351,16 +1497,6 @@ void os::ThreadCrashProtection::check_crash_protection(int sig, } } -#define check_with_errno(check_type, cond, msg) \ - do { \ - int err = errno; \ - check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \ - os::errno_name(err)); \ -} while (false) - -#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg) -#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg) - // POSIX unamed semaphores are not supported on OS X. #ifndef __APPLE__ diff --git a/src/hotspot/os/solaris/os_solaris.cpp b/src/hotspot/os/solaris/os_solaris.cpp index f136cec8275..ef7c1deaea4 100644 --- a/src/hotspot/os/solaris/os_solaris.cpp +++ b/src/hotspot/os/solaris/os_solaris.cpp @@ -2585,6 +2585,17 @@ char* os::pd_reserve_memory(size_t bytes, char* requested_addr, return addr; } +char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) { + assert(file_desc >= 0, "file_desc is not valid"); + char* result = pd_attempt_reserve_memory_at(bytes, requested_addr); + if (result != NULL) { + if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } + } + return result; +} + // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index c52cddd391c..656a119d4d4 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2904,6 +2904,75 @@ void os::large_page_init() { UseLargePages = success; } +int os::create_file_for_heap(const char* dir) { + + const char name_template[] = "/jvmheap.XXXXXX"; + char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal); + if (fullname == NULL) { + vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno))); + return -1; + } + + (void)strncpy(fullname, dir, strlen(dir)+1); + (void)strncat(fullname, name_template, strlen(name_template)); + + os::native_path(fullname); + + char *path = _mktemp(fullname); + if (path == NULL) { + warning("_mktemp could not create file name from template %s (%s)", fullname, os::strerror(errno)); + os::free(fullname); + return -1; + } + + int fd = _open(path, O_RDWR | O_CREAT | O_TEMPORARY | O_EXCL, S_IWRITE | S_IREAD); + + os::free(fullname); + if (fd < 0) { + warning("Problem opening file for heap (%s)", os::strerror(errno)); + return -1; + } + return fd; +} + +// If 'base' is not NULL, function will return NULL if it cannot get 'base' +char* os::map_memory_to_file(char* base, size_t size, int fd) { + assert(fd != -1, "File descriptor is not valid"); + + HANDLE fh = (HANDLE)_get_osfhandle(fd); +#ifdef _LP64 + HANDLE fileMapping = CreateFileMapping(fh, NULL, PAGE_READWRITE, + (DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), NULL); +#else + HANDLE fileMapping = CreateFileMapping(fh, NULL, PAGE_READWRITE, + 0, (DWORD)size, NULL); +#endif + if (fileMapping == NULL) { + if (GetLastError() == ERROR_DISK_FULL) { + vm_exit_during_initialization(err_msg("Could not allocate sufficient disk space for Java heap")); + } + else { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } + + return NULL; + } + + LPVOID addr = MapViewOfFileEx(fileMapping, FILE_MAP_WRITE, 0, 0, size, base); + + CloseHandle(fileMapping); + + return (char*)addr; +} + +char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd) { + assert(fd != -1, "File descriptor is not valid"); + assert(base != NULL, "Base address cannot be NULL"); + + release_memory(base, size); + return map_memory_to_file(base, size, fd); +} + // On win32, one cannot release just a part of reserved memory, it's an // all or nothing deal. When we split a reservation, we must break the // reservation into two reservations. @@ -2923,7 +2992,7 @@ void os::pd_split_reserved_memory(char *base, size_t size, size_t split, // Multiple threads can race in this code but it's not possible to unmap small sections of // virtual space to get requested alignment, like posix-like os's. // Windows prevents multiple thread from remapping over each other so this loop is thread-safe. -char* os::reserve_memory_aligned(size_t size, size_t alignment) { +char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { assert((alignment & (os::vm_allocation_granularity() - 1)) == 0, "Alignment must be a multiple of allocation granularity (page size)"); assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned"); @@ -2934,16 +3003,20 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment) { char* aligned_base = NULL; do { - char* extra_base = os::reserve_memory(extra_size, NULL, alignment); + char* extra_base = os::reserve_memory(extra_size, NULL, alignment, file_desc); if (extra_base == NULL) { return NULL; } // Do manual alignment aligned_base = align_up(extra_base, alignment); - os::release_memory(extra_base, extra_size); + if (file_desc != -1) { + os::unmap_memory(extra_base, extra_size); + } else { + os::release_memory(extra_base, extra_size); + } - aligned_base = os::reserve_memory(size, aligned_base); + aligned_base = os::reserve_memory(size, aligned_base, 0, file_desc); } while (aligned_base == NULL); @@ -2989,6 +3062,11 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { return reserve_memory(bytes, requested_addr); } +char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) { + assert(file_desc >= 0, "file_desc is not valid"); + return map_memory_to_file(requested_addr, bytes, file_desc); +} + size_t os::large_page_size() { return _large_page_size; } @@ -3490,9 +3568,7 @@ OSReturn os::get_native_priority(const Thread* const thread, void os::hint_no_preempt() {} void os::interrupt(Thread* thread) { - assert(!thread->is_Java_thread() || Thread::current() == thread || - Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); + debug_only(Thread::check_for_dangling_thread_pointer(thread);) OSThread* osthread = thread->osthread(); osthread->set_interrupted(true); @@ -3513,8 +3589,7 @@ void os::interrupt(Thread* thread) { bool os::is_interrupted(Thread* thread, bool clear_interrupted) { - assert(!thread->is_Java_thread() || Thread::current() == thread || Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); + debug_only(Thread::check_for_dangling_thread_pointer(thread);) OSThread* osthread = thread->osthread(); // There is no synchronization between the setting of the interrupt diff --git a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp index 0713b6de460..af9eb3fb85c 100644 --- a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp @@ -30,74 +30,6 @@ // Implementation of class atomic -#ifdef M68K - -/* - * __m68k_cmpxchg - * - * Atomically store newval in *ptr if *ptr is equal to oldval for user space. - * Returns newval on success and oldval if no exchange happened. - * This implementation is processor specific and works on - * 68020 68030 68040 and 68060. - * - * It will not work on ColdFire, 68000 and 68010 since they lack the CAS - * instruction. - * Using a kernelhelper would be better for arch complete implementation. - * - */ - -static inline int __m68k_cmpxchg(int oldval, int newval, volatile int *ptr) { - int ret; - __asm __volatile ("cas%.l %0,%2,%1" - : "=d" (ret), "+m" (*(ptr)) - : "d" (newval), "0" (oldval)); - return ret; -} - -/* Perform an atomic compare and swap: if the current value of `*PTR' - is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of - `*PTR' before the operation.*/ -static inline int m68k_compare_and_swap(int newval, - volatile int *ptr, - int oldval) { - for (;;) { - int prev = *ptr; - if (prev != oldval) - return prev; - - if (__m68k_cmpxchg (prev, newval, ptr) == newval) - // Success. - return prev; - - // We failed even though prev == oldval. Try again. - } -} - -/* Atomically add an int to memory. */ -static inline int m68k_add_and_fetch(int add_value, volatile int *ptr) { - for (;;) { - // Loop until success. - - int prev = *ptr; - - if (__m68k_cmpxchg (prev, prev + add_value, ptr) == prev + add_value) - return prev + add_value; - } -} - -/* Atomically write VALUE into `*PTR' and returns the previous - contents of `*PTR'. */ -static inline int m68k_lock_test_and_set(int newval, volatile int *ptr) { - for (;;) { - // Loop until success. - int prev = *ptr; - - if (__m68k_cmpxchg (prev, newval, ptr) == prev) - return prev; - } -} -#endif // M68K - #ifdef ARM /* @@ -175,12 +107,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co #ifdef ARM return add_using_helper(arm_add_and_fetch, add_value, dest); -#else -#ifdef M68K - return add_using_helper(m68k_add_and_fetch, add_value, dest); #else return __sync_add_and_fetch(dest, add_value); -#endif // M68K #endif // ARM } @@ -200,9 +128,6 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, STATIC_ASSERT(4 == sizeof(T)); #ifdef ARM return xchg_using_helper(arm_lock_test_and_set, exchange_value, dest); -#else -#ifdef M68K - return xchg_using_helper(m68k_lock_test_and_set, exchange_value, dest); #else // __sync_lock_test_and_set is a bizarrely named atomic exchange // operation. Note that some platforms only support this with the @@ -215,7 +140,6 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, // barrier. __sync_synchronize(); return result; -#endif // M68K #endif // ARM } @@ -242,12 +166,8 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, STATIC_ASSERT(4 == sizeof(T)); #ifdef ARM return cmpxchg_using_helper(arm_compare_and_swap, exchange_value, dest, compare_value); -#else -#ifdef M68K - return cmpxchg_using_helper(m68k_compare_and_swap, exchange_value, dest, compare_value); #else return __sync_val_compare_and_swap(dest, compare_value, exchange_value); -#endif // M68K #endif // ARM } diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp index 8e6dc325c4c..a36e4792efd 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp @@ -36,12 +36,18 @@ // Atomically copy 64 bits of data static void atomic_copy64(const volatile void *src, volatile void *dst) { -#if defined(PPC32) +#if defined(PPC32) && !defined(__SPE__) double tmp; asm volatile ("lfd %0, %2\n" "stfd %0, %1\n" : "=&f"(tmp), "=Q"(*(volatile double*)dst) : "Q"(*(volatile double*)src)); +#elif defined(PPC32) && defined(__SPE__) + long tmp; + asm volatile ("evldd %0, %2\n" + "evstdd %0, %1\n" + : "=&r"(tmp), "=Q"(*(volatile long*)dst) + : "Q"(*(volatile long*)src)); #elif defined(S390) && !defined(_LP64) double tmp; asm volatile ("ld %0, 0(%1)\n" diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 73229920040..fafd0ce7b27 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -4034,6 +4034,7 @@ int MatchRule::is_expensive() const { strcmp(opType,"ModF")==0 || strcmp(opType,"ModI")==0 || strcmp(opType,"SqrtD")==0 || + strcmp(opType,"SqrtF")==0 || strcmp(opType,"TanD")==0 || strcmp(opType,"ConvD2F")==0 || strcmp(opType,"ConvD2I")==0 || @@ -4167,7 +4168,7 @@ bool MatchRule::is_vector() const { "DivVF","DivVD", "AbsVF","AbsVD", "NegVF","NegVD", - "SqrtVD", + "SqrtVD","SqrtVF", "AndV" ,"XorV" ,"OrV", "AddReductionVI", "AddReductionVL", "AddReductionVF", "AddReductionVD", diff --git a/src/hotspot/share/aot/aotCodeHeap.cpp b/src/hotspot/share/aot/aotCodeHeap.cpp index 2a9b3982cd2..e22e228acf1 100644 --- a/src/hotspot/share/aot/aotCodeHeap.cpp +++ b/src/hotspot/share/aot/aotCodeHeap.cpp @@ -167,6 +167,7 @@ void AOTLib::verify_config() { verify_flag(_config->_compactFields, CompactFields, "CompactFields"); verify_flag(_config->_enableContended, EnableContended, "EnableContended"); verify_flag(_config->_restrictContended, RestrictContended, "RestrictContended"); + verify_flag(_config->_threadLocalHandshakes, ThreadLocalHandshakes, "ThreadLocalHandshakes"); if (!TieredCompilation && _config->_tieredAOT) { handle_config_error("Shared file %s error: Expected to run with tiered compilation on", _name); diff --git a/src/hotspot/share/aot/aotCodeHeap.hpp b/src/hotspot/share/aot/aotCodeHeap.hpp index 7bfd5c67531..ae6e9ff2556 100644 --- a/src/hotspot/share/aot/aotCodeHeap.hpp +++ b/src/hotspot/share/aot/aotCodeHeap.hpp @@ -92,7 +92,7 @@ typedef struct { } AOTHeader; typedef struct { - enum { CONFIG_SIZE = 7 * jintSize + 11 }; + enum { CONFIG_SIZE = 7 * jintSize + 12 }; // 7 int values int _config_size; int _narrowOopShift; @@ -101,7 +101,7 @@ typedef struct { int _fieldsAllocationStyle; int _objectAlignment; int _codeSegmentSize; - // byte[11] array map to boolean values here + // byte[12] array map to boolean values here bool _debug_VM; bool _useCompressedOops; bool _useCompressedClassPointers; @@ -113,6 +113,7 @@ typedef struct { bool _enableContended; bool _restrictContended; bool _omitAssertions; + bool _threadLocalHandshakes; } AOTConfiguration; class AOTLib : public CHeapObj { diff --git a/src/hotspot/share/aot/aotLoader.cpp b/src/hotspot/share/aot/aotLoader.cpp index c91c04b9b1b..9b77338e43d 100644 --- a/src/hotspot/share/aot/aotLoader.cpp +++ b/src/hotspot/share/aot/aotLoader.cpp @@ -146,15 +146,6 @@ void AOTLoader::initialize() { return; } - const char* home = Arguments::get_java_home(); - const char* file_separator = os::file_separator(); - - for (int i = 0; i < (int) (sizeof(modules) / sizeof(const char*)); i++) { - char library[JVM_MAXPATHLEN]; - jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s%s", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1", os::dll_file_extension()); - load_library(library, false); - } - // Scan the AOTLibrary option. if (AOTLibrary != NULL) { const int len = (int)strlen(AOTLibrary); @@ -172,6 +163,16 @@ void AOTLoader::initialize() { } } } + + // Load well-know AOT libraries from Java installation directory. + const char* home = Arguments::get_java_home(); + const char* file_separator = os::file_separator(); + + for (int i = 0; i < (int) (sizeof(modules) / sizeof(const char*)); i++) { + char library[JVM_MAXPATHLEN]; + jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s%s", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1", os::dll_file_extension()); + load_library(library, false); + } } } @@ -239,6 +240,21 @@ void AOTLoader::set_narrow_klass_shift() { } void AOTLoader::load_library(const char* name, bool exit_on_error) { + // Skip library if a library with the same name is already loaded. + const int file_separator = *os::file_separator(); + const char* start = strrchr(name, file_separator); + const char* new_name = (start == NULL) ? name : (start + 1); + FOR_ALL_AOT_LIBRARIES(lib) { + const char* lib_name = (*lib)->name(); + start = strrchr(lib_name, file_separator); + const char* old_name = (start == NULL) ? lib_name : (start + 1); + if (strcmp(old_name, new_name) == 0) { + if (PrintAOT) { + warning("AOT library %s is already loaded as %s.", name, lib_name); + } + return; + } + } char ebuf[1024]; void* handle = os::dll_load(name, ebuf, sizeof ebuf); if (handle == NULL) { diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp index 757c5e79274..980cd4d07dc 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.hpp @@ -196,8 +196,8 @@ class LIR_OprDesc: public CompilationResourceObj { // data opr-type opr-kind // +--------------+-------+-------+ // [max...........|7 6 5 4|3 2 1 0] - // ^ - // is_pointer bit + // ^ + // is_pointer bit // // lowest bit cleared, means it is a structure pointer // we need 4 bits to represent types diff --git a/src/hotspot/share/classfile/classListParser.cpp b/src/hotspot/share/classfile/classListParser.cpp index 8f7be316b50..b1fa759ae10 100644 --- a/src/hotspot/share/classfile/classListParser.cpp +++ b/src/hotspot/share/classfile/classListParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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,13 +23,32 @@ */ #include "precompiled.hpp" +#include "jvm.h" +#include "jimage.hpp" #include "classfile/classListParser.hpp" -#include "runtime/os.hpp" -#include "runtime/java.hpp" +#include "classfile/classLoaderExt.hpp" +#include "classfile/sharedClassUtil.hpp" +#include "classfile/symbolTable.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "memory/metaspaceShared.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/fieldType.hpp" +#include "runtime/javaCalls.hpp" +#include "utilities/defaultStream.hpp" +#include "utilities/hashtable.inline.hpp" +#include "utilities/macros.hpp" + +ClassListParser* ClassListParser::_instance = NULL; ClassListParser::ClassListParser(const char* file) { + assert(_instance == NULL, "must be singleton"); + _instance = this; _classlist_file = file; _file = fopen(file, "r"); + _line_no = 0; + _interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray(10, true); + if (_file == NULL) { char errmsg[JVM_MAXPATHLEN]; os::lasterror(errmsg, JVM_MAXPATHLEN); @@ -41,6 +60,7 @@ ClassListParser::~ClassListParser() { if (_file) { fclose(_file); } + _instance = NULL; } bool ClassListParser::parse_one_line() { @@ -48,10 +68,10 @@ bool ClassListParser::parse_one_line() { if (fgets(_line, sizeof(_line), _file) == NULL) { return false; } - int line_len = (int)strlen(_line); - if (line_len > _max_allowed_line_len) { - tty->print_cr("input line too long (must be no longer than %d chars)", _max_allowed_line_len); - vm_exit_during_initialization("Loading classlist failed"); + ++ _line_no; + _line_len = (int)strlen(_line); + if (_line_len > _max_allowed_line_len) { + error("input line too long (must be no longer than %d chars)", _max_allowed_line_len); } if (*_line == '#') { // comment continue; @@ -59,8 +79,380 @@ bool ClassListParser::parse_one_line() { break; } - // Remove trailing \r\n - _line[strcspn(_line, "\r\n")] = 0; + _id = _unspecified; + _super = _unspecified; + _interfaces->clear(); + _source = NULL; + _interfaces_specified = false; + + { + int len = (int)strlen(_line); + int i; + // Replace \t\r\n with ' ' + for (i=0; i 0) { + if (_line[len-1] == ' ') { + _line[len-1] = '\0'; + len --; + } else { + break; + } + } + _line_len = len; + _class_name = _line; + } + + if ((_token = strchr(_line, ' ')) == NULL) { + // No optional arguments are specified. + return true; + } + + // Mark the end of the name, and go to the next input char + *_token++ = '\0'; + + while (*_token) { + skip_whitespaces(); + + if (parse_int_option("id:", &_id)) { + continue; + } else if (parse_int_option("super:", &_super)) { + check_already_loaded("Super class", _super); + continue; + } else if (skip_token("interfaces:")) { + int i; + while (try_parse_int(&i)) { + check_already_loaded("Interface", i); + _interfaces->append(i); + } + } else if (skip_token("source:")) { + skip_whitespaces(); + _source = _token; + char* s = strchr(_token, ' '); + if (s == NULL) { + break; // end of input line + } else { + *s = '\0'; // mark the end of _source + _token = s+1; + } + } else { + error("Unknown input"); + } + } + + // if src is specified + // id super interfaces must all be specified + // loader may be specified + // else + // # the class is loaded from classpath + // id may be specified + // super, interfaces, loader must not be specified return true; } +void ClassListParser::skip_whitespaces() { + while (*_token == ' ' || *_token == '\t') { + _token ++; + } +} + +void ClassListParser::skip_non_whitespaces() { + while (*_token && *_token != ' ' && *_token != '\t') { + _token ++; + } +} + +void ClassListParser::parse_int(int* value) { + skip_whitespaces(); + if (sscanf(_token, "%i", value) == 1) { + skip_non_whitespaces(); + if (*value < 0) { + error("Error: negative integers not allowed (%d)", *value); + } + } else { + error("Error: expected integer"); + } +} + +bool ClassListParser::try_parse_int(int* value) { + skip_whitespaces(); + if (sscanf(_token, "%i", value) == 1) { + skip_non_whitespaces(); + return true; + } + return false; +} + +bool ClassListParser::skip_token(const char* option_name) { + size_t len = strlen(option_name); + if (strncmp(_token, option_name, len) == 0) { + _token += len; + return true; + } else { + return false; + } +} + +bool ClassListParser::parse_int_option(const char* option_name, int* value) { + if (skip_token(option_name)) { + if (*value != _unspecified) { + error("%s specified twice", option_name); + } else { + parse_int(value); + return true; + } + } + return false; +} + +void ClassListParser::print_specified_interfaces() { + const int n = _interfaces->length(); + jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n); + for (int i=0; iat(i)); + jio_fprintf(defaultStream::error_stream(), " %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name()); + } + jio_fprintf(defaultStream::error_stream(), "}\n"); +} + +void ClassListParser::print_actual_interfaces(InstanceKlass *ik) { + int n = ik->local_interfaces()->length(); + jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n); + for (int i = 0; i < n; i++) { + InstanceKlass* e = InstanceKlass::cast(ik->local_interfaces()->at(i)); + jio_fprintf(defaultStream::error_stream(), " %s\n", e->name()->as_klass_external_name()); + } + jio_fprintf(defaultStream::error_stream(), "}\n"); +} + +void ClassListParser::error(const char *msg, ...) { + va_list ap; + va_start(ap, msg); + int error_index = _token - _line; + if (error_index >= _line_len) { + error_index = _line_len - 1; + } + if (error_index < 0) { + error_index = 0; + } + + jio_fprintf(defaultStream::error_stream(), + "An error has occurred while processing class list file %s %d:%d.\n", + _classlist_file, _line_no, (error_index + 1)); + jio_vfprintf(defaultStream::error_stream(), msg, ap); + + if (_line_len <= 0) { + jio_fprintf(defaultStream::error_stream(), "\n"); + } else { + jio_fprintf(defaultStream::error_stream(), ":\n"); + for (int i=0; i<_line_len; i++) { + char c = _line[i]; + if (c == '\0') { + jio_fprintf(defaultStream::error_stream(), "%s", " "); + } else { + jio_fprintf(defaultStream::error_stream(), "%c", c); + } + } + jio_fprintf(defaultStream::error_stream(), "\n"); + for (int i=0; ilocal_interfaces()->length() != _interfaces->length()) { + print_specified_interfaces(); + print_actual_interfaces(k); + error("The number of interfaces (%d) specified in class list does not match the class file (%d)", + _interfaces->length(), k->local_interfaces()->length()); + } + + if (!SystemDictionaryShared::add_non_builtin_klass(class_name, ClassLoaderData::the_null_class_loader_data(), + k, THREAD)) { + error("Duplicated class %s", _class_name); + } + + // This tells JVM_FindLoadedClass to not find this class. + k->set_shared_classpath_index(UNREGISTERED_INDEX); + } + + return k; +} + +InstanceKlass* ClassListParser::load_current_class(TRAPS) { + TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name, THREAD); + guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); + + InstanceKlass *klass = NULL; + if (!is_loading_from_source()) { + if (is_super_specified()) { + error("If source location is not specified, super class must not be specified"); + } + if (are_interfaces_specified()) { + error("If source location is not specified, interface(s) must not be specified"); + } + + bool non_array = !FieldType::is_array(class_name_symbol); + + Handle s = java_lang_String::create_from_symbol(class_name_symbol, CHECK_0); + // Translate to external class name format, i.e., convert '/' chars to '.' + Handle string = java_lang_String::externalize_classname(s, CHECK_0); + JavaValue result(T_OBJECT); + InstanceKlass* spec_klass = non_array ? + SystemDictionary::ClassLoader_klass() : SystemDictionary::Class_klass(); + Symbol* method_name = non_array ? + vmSymbols::loadClass_name() : vmSymbols::forName_name(); + Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); + + if (non_array) { + JavaCalls::call_virtual(&result, + loader, //SystemDictionary::java_system_loader(), + spec_klass, + method_name, //vmSymbols::loadClass_name(), + vmSymbols::string_class_signature(), + string, + THREAD); + } else { + JavaCalls::call_static(&result, + spec_klass, + method_name, + vmSymbols::string_class_signature(), + string, + CHECK_NULL); + } + assert(result.get_type() == T_OBJECT, "just checking"); + oop obj = (oop) result.get_jobject(); + if (!HAS_PENDING_EXCEPTION && (obj != NULL)) { + if (non_array) { + klass = InstanceKlass::cast(java_lang_Class::as_Klass(obj)); + } else { + klass = static_cast(java_lang_Class::array_klass_acquire(obj)); + } + } else { // load classes in bootclasspath/a + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } + + if (non_array) { + Klass* k = SystemDictionary::resolve_or_null(class_name_symbol, CHECK_NULL); + if (k != NULL) { + klass = InstanceKlass::cast(k); + } else { + if (!HAS_PENDING_EXCEPTION) { + THROW_NULL(vmSymbols::java_lang_ClassNotFoundException()); + } + } + } + } + } else { + // If "source:" tag is specified, all super class and super interfaces must be specified in the + // class list file. + if (UseAppCDS) { + klass = load_class_from_source(class_name_symbol, CHECK_NULL); + } + } + + if (klass != NULL && is_id_specified()) { + int id = this->id(); + SystemDictionaryShared::update_shared_entry(klass, id); + InstanceKlass* old = table()->lookup(id); + if (old != NULL && old != klass) { + error("Duplicated ID %d for class %s", id, _class_name); + } + table()->add(id, klass); + } + + return klass; +} + +bool ClassListParser::is_loading_from_source() { + return (_source != NULL); +} + +InstanceKlass* ClassListParser::lookup_class_by_id(int id) { + InstanceKlass* klass = table()->lookup(id); + if (klass == NULL) { + error("Class ID %d has not been defined", id); + } + return klass; +} + + +InstanceKlass* ClassListParser::lookup_super_for_current_class(Symbol* super_name) { + if (!is_loading_from_source()) { + return NULL; + } + + InstanceKlass* k = lookup_class_by_id(super()); + if (super_name != k->name()) { + error("The specified super class %s (id %d) does not match actual super class %s", + k->name()->as_klass_external_name(), super(), + super_name->as_klass_external_name()); + } + return k; +} + +InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* interface_name) { + if (!is_loading_from_source()) { + return NULL; + } + + const int n = _interfaces->length(); + if (n == 0) { + error("Class %s implements the interface %s, but no interface has been specified in the input line", + _class_name, interface_name->as_klass_external_name()); + ShouldNotReachHere(); + } + + int i; + for (i=0; iat(i)); + if (interface_name == k->name()) { + return k; + } + } + + // interface_name is not specified by the "interfaces:" keyword. + print_specified_interfaces(); + error("The interface %s implemented by class %s does not match any of the specified interface IDs", + interface_name->as_klass_external_name(), _class_name); + ShouldNotReachHere(); + return NULL; +} + diff --git a/src/hotspot/share/classfile/classListParser.hpp b/src/hotspot/share/classfile/classListParser.hpp index 912ae3175a3..e6d48f41c8d 100644 --- a/src/hotspot/share/classfile/classListParser.hpp +++ b/src/hotspot/share/classfile/classListParser.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,30 +27,122 @@ #include "utilities/exceptions.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/hashtable.hpp" + +class CDSClassInfo; + +// Look up from ID -> InstanceKlass* +class ID2KlassTable : public Hashtable { +public: + ID2KlassTable() : Hashtable(1987, sizeof(HashtableEntry)) { } + void add(int id, InstanceKlass* klass) { + unsigned int hash = (unsigned int)id; + HashtableEntry* entry = new_entry(hash, klass); + add_entry(hash_to_index(hash), entry); + } + + InstanceKlass* lookup(int id) { + unsigned int hash = (unsigned int)id; + int index = hash_to_index(id); + for (HashtableEntry* e = bucket(index); e != NULL; e = e->next()) { + if (e->hash() == hash) { + return e->literal(); + } + } + return NULL; + } +}; class ClassListParser : public StackObj { enum { + _unspecified = -999, + // Max number of bytes allowed per line in the classlist. - // Theoretically Java class names could be 65535 bytes in length. In reality, + // Theoretically Java class names could be 65535 bytes in length. Also, an input line + // could have a very long path name up to JVM_MAXPATHLEN bytes in length. In reality, // 4K bytes is more than enough. _max_allowed_line_len = 4096, _line_buf_extra = 10, // for detecting input too long _line_buf_size = _max_allowed_line_len + _line_buf_extra }; + static ClassListParser* _instance; // the singleton. const char* _classlist_file; FILE* _file; - char _line[_line_buf_size]; // The buffer that holds the current line. + ID2KlassTable _id2klass_table; + + // The following field contains information from the *current* line being + // parsed. + char _line[_line_buf_size]; // The buffer that holds the current line. Some characters in + // the buffer may be overwritten by '\0' during parsing. + int _line_len; // Original length of the input line. + int _line_no; // Line number for current line being parsed + const char* _class_name; + int _id; + int _super; + GrowableArray* _interfaces; + bool _interfaces_specified; + const char* _source; + + bool parse_int_option(const char* option_name, int* value); + InstanceKlass* load_class_from_source(Symbol* class_name, TRAPS); + ID2KlassTable *table() { + return &_id2klass_table; + } + InstanceKlass* lookup_class_by_id(int id); + void print_specified_interfaces(); + void print_actual_interfaces(InstanceKlass *ik); public: ClassListParser(const char* file); ~ClassListParser(); + + static ClassListParser* instance() { + return _instance; + } bool parse_one_line(); + char* _token; + void error(const char* msg, ...); + void parse_int(int* value); + bool try_parse_int(int* value); + bool skip_token(const char* option_name); + void skip_whitespaces(); + void skip_non_whitespaces(); + + bool is_id_specified() { + return _id != _unspecified; + } + bool is_super_specified() { + return _super != _unspecified; + } + bool are_interfaces_specified() { + return _interfaces->length() > 0; + } + int id() { + assert(is_id_specified(), "do not query unspecified id"); + return _id; + } + int super() { + assert(is_super_specified(), "do not query unspecified super"); + return _super; + } + void check_already_loaded(const char* which, int id) { + if (_id2klass_table.lookup(id) == NULL) { + error("%s id %d is not yet loaded", which, id); + } + } const char* current_class_name() { - return _line; + return _class_name; } + + InstanceKlass* load_current_class(TRAPS); + + bool is_loading_from_source(); + + // Look up the super or interface of the current class being loaded + // (in this->load_current_class()). + InstanceKlass* lookup_super_for_current_class(Symbol* super_name); + InstanceKlass* lookup_interface_for_current_class(Symbol* interface_name); }; - - -#endif // SHARE_VM_MEMORY_CLASSLISTPARSER_HPP +#endif diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 3ba612ec747..202a170979f 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_CLASSFILE_CLASSLOADER_HPP #include "jimage.hpp" +#include "runtime/handles.hpp" #include "runtime/orderAccess.hpp" #include "runtime/perfData.hpp" #include "utilities/exceptions.hpp" @@ -42,6 +43,7 @@ class JImageFile; class ClassFileStream; class PackageEntry; +template class GrowableArray; class ClassPathEntry : public CHeapObj { private: diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp index 44efabec083..a7256bb8e72 100644 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ b/src/hotspot/share/classfile/classLoaderExt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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,14 +23,329 @@ */ #include "precompiled.hpp" +#include "classfile/classFileParser.hpp" +#include "classfile/classFileStream.hpp" #include "classfile/classListParser.hpp" +#include "classfile/classLoader.hpp" #include "classfile/classLoaderExt.hpp" -#include "classfile/symbolTable.hpp" -#include "classfile/systemDictionary.hpp" +#include "classfile/classLoaderData.inline.hpp" +#include "classfile/klassFactory.hpp" +#include "classfile/sharedClassUtil.hpp" +#include "classfile/sharedPathsMiscInfo.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "classfile/vmSymbols.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/filemap.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/oop.inline.hpp" +#include "oops/symbol.hpp" +#include "runtime/arguments.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/os.hpp" +#include "services/threadService.hpp" +#include "utilities/stringUtils.hpp" +jshort ClassLoaderExt::_app_paths_start_index = ClassLoaderExt::max_classpath_index; +bool ClassLoaderExt::_has_app_classes = false; +bool ClassLoaderExt::_has_platform_classes = false; + +void ClassLoaderExt::setup_app_search_path() { + assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS"); + _app_paths_start_index = ClassLoader::num_boot_classpath_entries(); + char* app_class_path = os::strdup(Arguments::get_appclasspath()); + + if (strcmp(app_class_path, ".") == 0) { + // This doesn't make any sense, even for AppCDS, so let's skip it. We + // don't want to throw an error here because -cp "." is usually assigned + // by the launcher when classpath is not specified. + trace_class_path("app loader class path (skipped)=", app_class_path); + } else { + trace_class_path("app loader class path=", app_class_path); + shared_paths_misc_info()->add_app_classpath(app_class_path); + ClassLoader::setup_app_search_path(app_class_path); + } +} + +char* ClassLoaderExt::read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS) { + const char* name = "META-INF/MANIFEST.MF"; + char* manifest; + jint size; + + assert(entry->is_jar_file(), "must be"); + manifest = (char*) ((ClassPathZipEntry*)entry )->open_entry(name, &size, true, CHECK_NULL); + + if (manifest == NULL) { // No Manifest + *manifest_size = 0; + return NULL; + } + + + if (clean_text) { + // See http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#JAR%20Manifest + // (1): replace all CR/LF and CR with LF + StringUtils::replace_no_expand(manifest, "\r\n", "\n"); + + // (2) remove all new-line continuation (remove all "\n " substrings) + StringUtils::replace_no_expand(manifest, "\n ", ""); + } + + *manifest_size = (jint)strlen(manifest); + return manifest; +} + +char* ClassLoaderExt::get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size) { + const char* tag = "Class-Path: "; + const int tag_len = (int)strlen(tag); + char* found = NULL; + char* line_start = manifest; + char* end = manifest + manifest_size; + + assert(*end == 0, "must be nul-terminated"); + + while (line_start < end) { + char* line_end = strchr(line_start, '\n'); + if (line_end == NULL) { + // JAR spec require the manifest file to be terminated by a new line. + break; + } + if (strncmp(tag, line_start, tag_len) == 0) { + if (found != NULL) { + // Same behavior as jdk/src/share/classes/java/util/jar/Attributes.java + // If duplicated entries are found, the last one is used. + tty->print_cr("Warning: Duplicate name in Manifest: %s.\n" + "Ensure that the manifest does not have duplicate entries, and\n" + "that blank lines separate individual sections in both your\n" + "manifest and in the META-INF/MANIFEST.MF entry in the jar file:\n%s\n", tag, jar_path); + } + found = line_start + tag_len; + assert(found <= line_end, "sanity"); + *line_end = '\0'; + } + line_start = line_end + 1; + } + return found; +} + +void ClassLoaderExt::process_jar_manifest(ClassPathEntry* entry, + bool check_for_duplicates) { + Thread* THREAD = Thread::current(); + ResourceMark rm(THREAD); + jint manifest_size; + char* manifest = read_manifest(entry, &manifest_size, CHECK); + + if (manifest == NULL) { + return; + } + + if (strstr(manifest, "Extension-List:") != NULL) { + tty->print_cr("-Xshare:dump does not support Extension-List in JAR manifest: %s", entry->name()); + vm_exit(1); + } + + char* cp_attr = get_class_path_attr(entry->name(), manifest, manifest_size); + + if (cp_attr != NULL && strlen(cp_attr) > 0) { + trace_class_path("found Class-Path: ", cp_attr); + + char sep = os::file_separator()[0]; + const char* dir_name = entry->name(); + const char* dir_tail = strrchr(dir_name, sep); + int dir_len; + if (dir_tail == NULL) { + dir_len = 0; + } else { + dir_len = dir_tail - dir_name + 1; + } + + // Split the cp_attr by spaces, and add each file + char* file_start = cp_attr; + char* end = file_start + strlen(file_start); + + while (file_start < end) { + char* file_end = strchr(file_start, ' '); + if (file_end != NULL) { + *file_end = 0; + file_end += 1; + } else { + file_end = end; + } + + int name_len = (int)strlen(file_start); + if (name_len > 0) { + ResourceMark rm(THREAD); + char* libname = NEW_RESOURCE_ARRAY(char, dir_len + name_len + 1); + *libname = 0; + strncat(libname, dir_name, dir_len); + strncat(libname, file_start, name_len); + trace_class_path("library = ", libname); + ClassLoader::update_class_path_entry_list(libname, true, false); + } + + file_start = file_end; + } + } +} + +void ClassLoaderExt::setup_search_paths() { + if (UseAppCDS) { + shared_paths_misc_info()->record_app_offset(); + ClassLoaderExt::setup_app_search_path(); + } +} + +Thread* ClassLoaderExt::Context::_dump_thread = NULL; + +bool ClassLoaderExt::check(ClassLoaderExt::Context *context, + const ClassFileStream* stream, + const int classpath_index) { + if (stream != NULL) { + // Ignore any App classes from signed JAR file during CDS archiving + // dumping + if (DumpSharedSpaces && + SharedClassUtil::is_classpath_entry_signed(classpath_index) && + classpath_index >= _app_paths_start_index) { + tty->print_cr("Preload Warning: Skipping %s from signed JAR", + context->class_name()); + return false; + } + if (classpath_index >= _app_paths_start_index) { + _has_app_classes = true; + _has_platform_classes = true; + } + } + + return true; +} + +void ClassLoaderExt::record_result(ClassLoaderExt::Context *context, + Symbol* class_name, + const s2 classpath_index, + InstanceKlass* result, + TRAPS) { + assert(DumpSharedSpaces, "Sanity"); + + // We need to remember where the class comes from during dumping. + oop loader = result->class_loader(); + s2 classloader_type = ClassLoader::BOOT_LOADER; + if (SystemDictionary::is_system_class_loader(loader)) { + classloader_type = ClassLoader::APP_LOADER; + ClassLoaderExt::set_has_app_classes(); + } else if (SystemDictionary::is_platform_class_loader(loader)) { + classloader_type = ClassLoader::PLATFORM_LOADER; + ClassLoaderExt::set_has_platform_classes(); + } + result->set_shared_classpath_index(classpath_index); + result->set_class_loader_type(classloader_type); +} + +void ClassLoaderExt::finalize_shared_paths_misc_info() { + if (UseAppCDS) { + if (!_has_app_classes) { + shared_paths_misc_info()->pop_app(); + } + } +} + +// Load the class of the given name from the location given by path. The path is specified by +// the "source:" in the class list file (see classListParser.cpp), and can be a directory or +// a JAR file. +InstanceKlass* ClassLoaderExt::load_class(Symbol* name, const char* path, TRAPS) { + + assert(name != NULL, "invariant"); + assert(DumpSharedSpaces && UseAppCDS, "this function is only used with -Xshare:dump and -XX:+UseAppCDS"); + ResourceMark rm(THREAD); + const char* class_name = name->as_C_string(); + + const char* file_name = file_name_for_class_name(class_name, + name->utf8_length()); + assert(file_name != NULL, "invariant"); + + // Lookup stream for parsing .class file + ClassFileStream* stream = NULL; + ClassPathEntry* e = find_classpath_entry_from_cache(path, CHECK_NULL); + if (e == NULL) { + return NULL; + } + { + PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), + ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_LOAD); + stream = e->open_stream(file_name, CHECK_NULL); + } + + if (NULL == stream) { + tty->print_cr("Preload Warning: Cannot find %s", class_name); + return NULL; + } + + assert(stream != NULL, "invariant"); + stream->set_verify(true); + + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + Handle protection_domain; + + InstanceKlass* result = KlassFactory::create_from_stream(stream, + name, + loader_data, + protection_domain, + NULL, // host_klass + NULL, // cp_patches + THREAD); + + if (HAS_PENDING_EXCEPTION) { + tty->print_cr("Preload Error: Failed to load %s", class_name); + return NULL; + } + result->set_shared_classpath_index(UNREGISTERED_INDEX); + SystemDictionaryShared::set_shared_class_misc_info(result, stream); + return result; +} + +struct CachedClassPathEntry { + const char* _path; + ClassPathEntry* _entry; +}; + +static GrowableArray* cached_path_entries = NULL; + +ClassPathEntry* ClassLoaderExt::find_classpath_entry_from_cache(const char* path, TRAPS) { + // This is called from dump time so it's single threaded and there's no need for a lock. + assert(DumpSharedSpaces && UseAppCDS, "this function is only used with -Xshare:dump and -XX:+UseAppCDS"); + if (cached_path_entries == NULL) { + cached_path_entries = new (ResourceObj::C_HEAP, mtClass) GrowableArray(20, /*c heap*/ true); + } + CachedClassPathEntry ccpe; + for (int i=0; ilength(); i++) { + ccpe = cached_path_entries->at(i); + if (strcmp(ccpe._path, path) == 0) { + if (i != 0) { + // Put recent entries at the beginning to speed up searches. + cached_path_entries->remove_at(i); + cached_path_entries->insert_before(0, ccpe); + } + return ccpe._entry; + } + } + + struct stat st; + if (os::stat(path, &st) != 0) { + // File or directory not found + return NULL; + } + ClassPathEntry* new_entry = NULL; + + new_entry = create_class_path_entry(path, &st, false, false, CHECK_NULL); + if (new_entry == NULL) { + return NULL; + } + ccpe._path = strdup(path); + ccpe._entry = new_entry; + cached_path_entries->insert_before(0, ccpe); + return new_entry; +} Klass* ClassLoaderExt::load_one_class(ClassListParser* parser, TRAPS) { - TempNewSymbol class_name_symbol = SymbolTable::new_symbol(parser->current_class_name(), THREAD); - guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); - return SystemDictionary::resolve_or_null(class_name_symbol, THREAD); + return parser->load_current_class(THREAD); } diff --git a/src/hotspot/share/classfile/classLoaderExt.hpp b/src/hotspot/share/classfile/classLoaderExt.hpp index 09cb592b0d6..27e9ce25ef5 100644 --- a/src/hotspot/share/classfile/classLoaderExt.hpp +++ b/src/hotspot/share/classfile/classLoaderExt.hpp @@ -26,65 +26,152 @@ #define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP #include "classfile/classLoader.hpp" -#include "classfile/systemDictionary.hpp" -#include "oops/instanceKlass.hpp" -#include "runtime/handles.hpp" +#include "utilities/macros.hpp" -class ClassListParser; +CDS_ONLY(class SharedPathsMiscInfoExt;) +CDS_ONLY(class ClassListParser;) class ClassLoaderExt: public ClassLoader { // AllStatic public: - + enum SomeConstants { + max_classpath_index = 0x7fff + }; + // ClassLoaderExt::Context -- + // + // This is used by DumpSharedSpaces only - it enforces the same classloader + // delegation model as would be in run-time. I.e., + // + classes defined by the NULL class loader cannot load classes in the PLATFORM or APP paths. + // + classes defined by the PLATFORM class loader cannot load classes in the APP paths. class Context { + static Thread* _dump_thread; + const char* _class_name; const char* _file_name; public: + const char* class_name() { + return _class_name; + } + const char* file_name() { + return _file_name; + } + Context(const char* class_name, const char* file_name, TRAPS) { + _class_name = class_name; _file_name = file_name; +#if INCLUDE_CDS + if (!DumpSharedSpaces && !UseSharedSpaces) { + // Must not modify _app_paths_start_index if we're not using CDS. + assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be"); + } +#endif } bool check(const ClassFileStream* stream, const int classpath_index) { - return true; + CDS_ONLY(return ClassLoaderExt::check(this, stream, classpath_index);) + NOT_CDS(return true;) } bool should_verify(int classpath_index) { - return false; + CDS_ONLY(return (classpath_index >= _app_paths_start_index);) + NOT_CDS(return false;) } void record_result(Symbol* class_name, const s2 classpath_index, - InstanceKlass* result, TRAPS) { + InstanceKlass* result, + TRAPS) { #if INCLUDE_CDS - assert(DumpSharedSpaces, "Sanity"); - oop loader = result->class_loader(); - s2 classloader_type = ClassLoader::BOOT_LOADER; - if (SystemDictionary::is_system_class_loader(loader)) { - classloader_type = ClassLoader::APP_LOADER; - ClassLoaderExt::set_has_app_classes(); - } else if (SystemDictionary::is_platform_class_loader(loader)) { - classloader_type = ClassLoader::PLATFORM_LOADER; - ClassLoaderExt::set_has_platform_classes(); - } - result->set_shared_classpath_index(classpath_index); - result->set_class_loader_type(classloader_type); + ClassLoaderExt::record_result(this, class_name, classpath_index, result, THREAD); #endif } - }; + ~Context() { +#if INCLUDE_CDS + if (!DumpSharedSpaces && !UseSharedSpaces) { + // Must not modify app_paths_start_index if we're not using CDS. + assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be"); + } +#endif + } + }; // end ClassLoaderExt::Context + +private: +#if INCLUDE_CDS + static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size); + static void setup_app_search_path(); // Only when -Xshare:dump + static SharedPathsMiscInfoExt* shared_paths_misc_info() { + return (SharedPathsMiscInfoExt*)_shared_paths_misc_info; + } + static jshort _app_paths_start_index; // index of first app JAR in shared classpath entry table + static bool _has_app_classes; + static bool _has_platform_classes; +#endif + +public: + CDS_ONLY(static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates);) + + // Called by JVMTI code to add boot classpath static void append_boot_classpath(ClassPathEntry* new_entry) { +#if INCLUDE_CDS + if (UseAppCDS) { + warning("UseAppCDS is disabled because bootstrap classpath has been appended"); + UseAppCDS = false; + } +#endif ClassLoader::add_to_boot_append_entries(new_entry); } - static void setup_search_paths() {} - static bool is_boot_classpath(int classpath_index) { - return true; - } - static Klass* load_one_class(ClassListParser* parser, TRAPS); + + static void setup_search_paths() NOT_CDS_RETURN; + #if INCLUDE_CDS - static void set_has_app_classes() {} - static void set_has_platform_classes() {} +private: + static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS); + static ClassPathEntry* find_classpath_entry_from_cache(const char* path, TRAPS); + +public: static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) { - return NULL; + // Remove all the new-line continuations (which wrap long lines at 72 characters, see + // http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#JAR%20Manifest), so + // that the manifest is easier to parse. + return read_manifest(entry, manifest_size, true, THREAD); + } + static char* read_raw_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) { + // Do not remove new-line continuations, so we can easily pass it as an argument to + // java.util.jar.Manifest.getManifest() at run-time. + return read_manifest(entry, manifest_size, false, THREAD); + } + + static void finalize_shared_paths_misc_info(); + + static jshort app_paths_start_index() { return _app_paths_start_index; } + + static void init_paths_start_index(jshort app_start) { + _app_paths_start_index = app_start; + } + + static bool is_boot_classpath(int classpath_index) { + return classpath_index < _app_paths_start_index; + } + + static bool has_platform_or_app_classes() { + return _has_app_classes || _has_platform_classes; + } + + static bool check(class ClassLoaderExt::Context *context, + const ClassFileStream* stream, + const int classpath_index); + + static void record_result(class ClassLoaderExt::Context *context, + Symbol* class_name, + const s2 classpath_index, + InstanceKlass* result, TRAPS); + static InstanceKlass* load_class(Symbol* h_name, const char* path, TRAPS); + static Klass* load_one_class(ClassListParser* parser, TRAPS); + static void set_has_app_classes() { + _has_app_classes = true; + } + static void set_has_platform_classes() { + _has_platform_classes = true; } - static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates) {} #endif }; diff --git a/src/hotspot/share/classfile/klassFactory.hpp b/src/hotspot/share/classfile/klassFactory.hpp index cb3ed851dd9..c08f8b9a119 100644 --- a/src/hotspot/share/classfile/klassFactory.hpp +++ b/src/hotspot/share/classfile/klassFactory.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_CLASSFILE_KLASSFACTORY_HPP #define SHARE_VM_CLASSFILE_KLASSFACTORY_HPP -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "runtime/handles.hpp" class ClassFileStream; diff --git a/src/hotspot/share/classfile/sharedClassUtil.cpp b/src/hotspot/share/classfile/sharedClassUtil.cpp new file mode 100644 index 00000000000..2080472e2f1 --- /dev/null +++ b/src/hotspot/share/classfile/sharedClassUtil.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014, 2017, 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 "classfile/classLoader.hpp" +#include "classfile/classLoaderExt.hpp" +#include "classfile/dictionary.hpp" +#include "classfile/javaClasses.hpp" +#include "classfile/sharedClassUtil.hpp" +#include "classfile/stringTable.hpp" +#include "classfile/symbolTable.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "memory/filemap.hpp" +#include "memory/metadataFactory.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "runtime/arguments.hpp" +#include "runtime/java.hpp" +#include "runtime/os.hpp" + +class ManifestStream: public ResourceObj { + private: + u1* _buffer_start; // Buffer bottom + u1* _buffer_end; // Buffer top (one past last element) + u1* _current; // Current buffer position + + public: + // Constructor + ManifestStream(u1* buffer, int length) : _buffer_start(buffer), + _current(buffer) { + _buffer_end = buffer + length; + } + + static bool is_attr(u1* attr, const char* name) { + return strncmp((const char*)attr, name, strlen(name)) == 0; + } + + static char* copy_attr(u1* value, size_t len) { + char* buf = NEW_RESOURCE_ARRAY(char, len + 1); + strncpy(buf, (char*)value, len); + buf[len] = 0; + return buf; + } + + // The return value indicates if the JAR is signed or not + bool check_is_signed() { + u1* attr = _current; + bool isSigned = false; + while (_current < _buffer_end) { + if (*_current == '\n') { + *_current = '\0'; + u1* value = (u1*)strchr((char*)attr, ':'); + if (value != NULL) { + assert(*(value+1) == ' ', "Unrecognized format" ); + if (strstr((char*)attr, "-Digest") != NULL) { + isSigned = true; + break; + } + } + *_current = '\n'; // restore + attr = _current + 1; + } + _current ++; + } + return isSigned; + } +}; + +void SharedPathsMiscInfoExt::print_path(outputStream* out, int type, const char* path) { + switch(type) { + case APP: + ClassLoader::trace_class_path("Expecting -Djava.class.path=", path); + break; + default: + SharedPathsMiscInfo::print_path(out, type, path); + } +} + +bool SharedPathsMiscInfoExt::check(jint type, const char* path) { + + switch (type) { + case APP: + { + // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar + size_t len = strlen(path); + const char *appcp = Arguments::get_appclasspath(); + assert(appcp != NULL, "NULL app classpath"); + size_t appcp_len = strlen(appcp); + if (appcp_len < len) { + return fail("Run time APP classpath is shorter than the one at dump time: ", appcp); + } + ResourceMark rm; + char* tmp_path; + if (len == appcp_len) { + tmp_path = (char*)appcp; + } else { + tmp_path = NEW_RESOURCE_ARRAY(char, len + 1); + strncpy(tmp_path, appcp, len); + tmp_path[len] = 0; + } + if (os::file_name_strcmp(path, tmp_path) != 0) { + return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp); + } + if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) { + return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp); + } + } + break; + default: + return SharedPathsMiscInfo::check(type, path); + } + + return true; +} + +void SharedClassUtil::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* e, TRAPS) { + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)e; + ResourceMark rm(THREAD); + jint manifest_size; + bool isSigned; + + if (cpe->is_jar_file()) { + char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK); + if (manifest != NULL) { + ManifestStream* stream = new ManifestStream((u1*)manifest, + manifest_size); + isSigned = stream->check_is_signed(); + if (isSigned) { + ent->_is_signed = true; + } else { + // Copy the manifest into the shared archive + manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK); + Array* buf = MetadataFactory::new_array(loader_data, + manifest_size, + THREAD); + char* p = (char*)(buf->data()); + memcpy(p, manifest, manifest_size); + ent->set_manifest(buf); + ent->_is_signed = false; + } + } + } +} + +void SharedClassUtil::initialize(TRAPS) { + if (UseSharedSpaces) { + int size = FileMapInfo::get_number_of_share_classpaths(); + if (size > 0) { + SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD); + if (!DumpSharedSpaces) { + FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header(); + ClassLoaderExt::init_paths_start_index(header->_app_paths_start_index); + } + } + } + + if (DumpSharedSpaces) { + if (SharedArchiveConfigFile) { + read_extra_data(SharedArchiveConfigFile, THREAD); + } + } +} + +void SharedClassUtil::read_extra_data(const char* filename, TRAPS) { + HashtableTextDump reader(filename); + reader.check_version("VERSION: 1.0"); + + while (reader.remain() > 0) { + int utf8_length; + int prefix_type = reader.scan_prefix(&utf8_length); + ResourceMark rm(THREAD); + char* utf8_buffer = NEW_RESOURCE_ARRAY(char, utf8_length); + reader.get_utf8(utf8_buffer, utf8_length); + + if (prefix_type == HashtableTextDump::SymbolPrefix) { + SymbolTable::new_symbol(utf8_buffer, utf8_length, THREAD); + } else{ + assert(prefix_type == HashtableTextDump::StringPrefix, "Sanity"); + utf8_buffer[utf8_length] = '\0'; + oop s = StringTable::intern(utf8_buffer, THREAD); + } + } +} + +bool SharedClassUtil::is_classpath_entry_signed(int classpath_index) { + assert(classpath_index >= 0, "Sanity"); + SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*) + FileMapInfo::shared_classpath(classpath_index); + return ent->_is_signed; +} + +void FileMapHeaderExt::populate(FileMapInfo* mapinfo, size_t alignment) { + FileMapInfo::FileMapHeader::populate(mapinfo, alignment); + + ClassLoaderExt::finalize_shared_paths_misc_info(); + _app_paths_start_index = ClassLoaderExt::app_paths_start_index(); + + _verify_local = BytecodeVerificationLocal; + _verify_remote = BytecodeVerificationRemote; + _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes(); +} + +bool FileMapHeaderExt::validate() { + if (UseAppCDS) { + const char* prop = Arguments::get_property("java.system.class.loader"); + if (prop != NULL) { + warning("UseAppCDS is disabled because the java.system.class.loader property is specified (value = \"%s\"). " + "To enable UseAppCDS, this property must be not be set", prop); + UseAppCDS = false; + } + } + + if (!FileMapInfo::FileMapHeader::validate()) { + return false; + } + + // For backwards compatibility, we don't check the verification setting + // if the archive only contains system classes. + if (_has_platform_or_app_classes && + ((!_verify_local && BytecodeVerificationLocal) || + (!_verify_remote && BytecodeVerificationRemote))) { + FileMapInfo::fail_continue("The shared archive file was created with less restrictive " + "verification setting than the current setting."); + return false; + } + + return true; +} diff --git a/src/hotspot/share/classfile/sharedClassUtil.hpp b/src/hotspot/share/classfile/sharedClassUtil.hpp index 236087f1871..c3b7f603466 100644 --- a/src/hotspot/share/classfile/sharedClassUtil.hpp +++ b/src/hotspot/share/classfile/sharedClassUtil.hpp @@ -27,37 +27,108 @@ #include "classfile/sharedPathsMiscInfo.hpp" #include "memory/filemap.hpp" +#include "classfile/classLoaderExt.hpp" +#include "classfile/dictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "oops/klass.hpp" -class SharedClassUtil : AllStatic { +class FileMapHeaderExt: public FileMapInfo::FileMapHeader { public: + jshort _app_paths_start_index; // Index of first app classpath entry + bool _verify_local; // BytecodeVerificationLocal setting + bool _verify_remote; // BytecodeVerificationRemote setting + bool _has_platform_or_app_classes; // Archive contains app classes - static SharedPathsMiscInfo* allocate_shared_paths_misc_info() { - return new SharedPathsMiscInfo(); + FileMapHeaderExt() { + _has_platform_or_app_classes = true; + } + virtual void populate(FileMapInfo* mapinfo, size_t alignment); + virtual bool validate(); +}; + +// In addition to SharedPathsMiscInfo, the following information is also stored +// +// +// + The value of Arguments::get_appclasspath() used during dumping. +// +class SharedPathsMiscInfoExt : public SharedPathsMiscInfo { +private: + int _app_offset; +public: + enum { + APP = 5 + }; + + virtual const char* type_name(int type) { + switch (type) { + case APP: return "APP"; + default: return SharedPathsMiscInfo::type_name(type); + } } - static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) { - return new SharedPathsMiscInfo(buf, size); + virtual void print_path(outputStream* out, int type, const char* path); + + SharedPathsMiscInfoExt() : SharedPathsMiscInfo() { + _app_offset = 0; + } + SharedPathsMiscInfoExt(char* buf, int size) : SharedPathsMiscInfo(buf, size) { + _app_offset = 0; } - static FileMapInfo::FileMapHeader* allocate_file_map_header() { - return new FileMapInfo::FileMapHeader(); + virtual bool check(jint type, const char* path); + + void add_app_classpath(const char* path) { + add_path(path, APP); } - static size_t file_map_header_size() { - return sizeof(FileMapInfo::FileMapHeader); + void record_app_offset() { + _app_offset = get_used_bytes(); } - - static size_t shared_class_path_entry_size() { - return sizeof(SharedClassPathEntry); - } - - static void update_shared_classpath(ClassPathEntry *cpe, - SharedClassPathEntry* ent, TRAPS) {} - static void initialize(TRAPS) {} - - inline static bool is_shared_boot_class(Klass* klass) { - return (klass->_shared_class_path_index >= 0); + void pop_app() { + _cur_ptr = _buf_start + _app_offset; + write_jint(0); } }; +class SharedClassPathEntryExt: public SharedClassPathEntry { +public: + //Maniest attributes + bool _is_signed; + void set_manifest(Array* manifest) { + _manifest = manifest; + } +}; + +class SharedClassUtil : AllStatic { +public: + static SharedPathsMiscInfo* allocate_shared_paths_misc_info() { + return new SharedPathsMiscInfoExt(); + } + + static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) { + return new SharedPathsMiscInfoExt(buf, size); + } + + static FileMapInfo::FileMapHeader* allocate_file_map_header() { + return new FileMapHeaderExt(); + } + + static size_t file_map_header_size() { + return sizeof(FileMapHeaderExt); + } + + static size_t shared_class_path_entry_size() { + return sizeof(SharedClassPathEntryExt); + } + + static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS); + static void initialize(TRAPS); + +private: + static void read_extra_data(const char* filename, TRAPS); + +public: + static bool is_classpath_entry_signed(int classpath_index); +}; + #endif // SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP diff --git a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp index 7f9314ea63c..98a76d1455d 100644 --- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp +++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp @@ -34,6 +34,18 @@ #include "runtime/arguments.hpp" #include "utilities/ostream.hpp" +SharedPathsMiscInfo::SharedPathsMiscInfo() { + _buf_size = INITIAL_BUF_SIZE; + _cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass); + _allocated = true; +} + +SharedPathsMiscInfo::~SharedPathsMiscInfo() { + if (_allocated) { + FREE_C_HEAP_ARRAY(char, _buf_start); + } +} + void SharedPathsMiscInfo::add_path(const char* path, int type) { log_info(class, path)("type=%s ", type_name(type)); ClassLoader::trace_class_path("add misc shared path ", path); @@ -127,7 +139,8 @@ bool SharedPathsMiscInfo::check() { bool SharedPathsMiscInfo::check(jint type, const char* path) { switch (type) { case BOOT: - if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) { + // In the future we should perform the check based on the content of the mapped archive. + if (UseAppCDS && os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) { return fail("[BOOT classpath mismatch, actual =", Arguments::get_sysclasspath()); } break; diff --git a/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp b/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp index 2099dc24881..e5576156e67 100644 --- a/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp +++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp @@ -74,11 +74,7 @@ public: INITIAL_BUF_SIZE = 128 }; // This constructor is used when creating the misc information (during dump) - SharedPathsMiscInfo() { - _buf_size = INITIAL_BUF_SIZE; - _cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass); - _allocated = true; - } + SharedPathsMiscInfo(); // This constructor is used when validating the misc info (during run time) SharedPathsMiscInfo(char *buff, int size) { _cur_ptr = _buf_start = buff; @@ -86,11 +82,8 @@ public: _buf_size = size; _allocated = false; } - ~SharedPathsMiscInfo() { - if (_allocated) { - FREE_C_HEAP_ARRAY(char, _buf_start); - } - } + ~SharedPathsMiscInfo(); + int get_used_bytes() { return _cur_ptr - _buf_start; } diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index a08bd225277..77538a53e5c 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_CLASSFILE_STRINGTABLE_HPP #define SHARE_VM_CLASSFILE_STRINGTABLE_HPP -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "utilities/hashtable.hpp" template class CompactHashtable; diff --git a/src/hotspot/share/classfile/symbolTable.hpp b/src/hotspot/share/classfile/symbolTable.hpp index 931669650b5..bf3c36257da 100644 --- a/src/hotspot/share/classfile/symbolTable.hpp +++ b/src/hotspot/share/classfile/symbolTable.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP #define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "oops/symbol.hpp" #include "utilities/hashtable.hpp" diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index df4a38f0306..f760c758273 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1087,7 +1087,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, #if INCLUDE_CDS ResourceMark rm(THREAD); if (DumpSharedSpaces && !class_loader.is_null() && - !ArgumentsExt::using_AppCDS() && strcmp(class_name->as_C_string(), "Unnamed") != 0) { + !UseAppCDS && strcmp(class_name->as_C_string(), "Unnamed") != 0) { // If AppCDS is not enabled, don't define the class at dump time (except for the "Unnamed" // class, which is used by MethodHandles). THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string()); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp new file mode 100644 index 00000000000..692ba891823 --- /dev/null +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -0,0 +1,1086 @@ +/* + * Copyright (c) 2014, 2017, 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 "classfile/classFileStream.hpp" +#include "classfile/classListParser.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderExt.hpp" +#include "classfile/compactHashtable.inline.hpp" +#include "classfile/dictionary.hpp" +#include "classfile/javaClasses.hpp" +#include "classfile/sharedClassUtil.hpp" +#include "classfile/symbolTable.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "classfile/verificationType.hpp" +#include "classfile/vmSymbols.hpp" +#include "logging/log.hpp" +#include "memory/allocation.hpp" +#include "memory/filemap.hpp" +#include "memory/metadataFactory.hpp" +#include "memory/metaspaceClosure.hpp" +#include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klass.inline.hpp" +#include "oops/objArrayOop.inline.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "utilities/hashtable.inline.hpp" +#include "utilities/stringUtils.hpp" + + +objArrayOop SystemDictionaryShared::_shared_protection_domains = NULL; +objArrayOop SystemDictionaryShared::_shared_jar_urls = NULL; +objArrayOop SystemDictionaryShared::_shared_jar_manifests = NULL; + +static Mutex* SharedDictionary_lock = NULL; + +void SystemDictionaryShared::initialize(TRAPS) { + if (_java_system_loader != NULL) { + SharedDictionary_lock = new Mutex(Mutex::leaf, "SharedDictionary_lock", true); + + // These classes need to be initialized before calling get_shared_jar_manifest(), etc. + SystemDictionary::ByteArrayInputStream_klass()->initialize(CHECK); + SystemDictionary::File_klass()->initialize(CHECK); + SystemDictionary::Jar_Manifest_klass()->initialize(CHECK); + SystemDictionary::CodeSource_klass()->initialize(CHECK); + } +} + +oop SystemDictionaryShared::shared_protection_domain(int index) { + return _shared_protection_domains->obj_at(index); +} + +oop SystemDictionaryShared::shared_jar_url(int index) { + return _shared_jar_urls->obj_at(index); +} + +oop SystemDictionaryShared::shared_jar_manifest(int index) { + return _shared_jar_manifests->obj_at(index); +} + + +Handle SystemDictionaryShared::get_shared_jar_manifest(int shared_path_index, TRAPS) { + Handle empty; + Handle manifest ; + if (shared_jar_manifest(shared_path_index) == NULL) { + SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)FileMapInfo::shared_classpath(shared_path_index); + long size = ent->manifest_size(); + if (size <= 0) { + return empty; // No manifest - return NULL handle + } + + // ByteArrayInputStream bais = new ByteArrayInputStream(buf); + InstanceKlass* bais_klass = SystemDictionary::ByteArrayInputStream_klass(); + Handle bais = bais_klass->allocate_instance_handle(CHECK_(empty)); + { + const char* src = ent->manifest(); + assert(src != NULL, "No Manifest data"); + typeArrayOop buf = oopFactory::new_byteArray(size, CHECK_(empty)); + typeArrayHandle bufhandle(THREAD, buf); + char* dst = (char*)(buf->byte_at_addr(0)); + memcpy(dst, src, (size_t)size); + + JavaValue result(T_VOID); + JavaCalls::call_special(&result, bais, bais_klass, + vmSymbols::object_initializer_name(), + vmSymbols::byte_array_void_signature(), + bufhandle, CHECK_(empty)); + } + + // manifest = new Manifest(bais) + InstanceKlass* manifest_klass = SystemDictionary::Jar_Manifest_klass(); + manifest = manifest_klass->allocate_instance_handle(CHECK_(empty)); + { + JavaValue result(T_VOID); + JavaCalls::call_special(&result, manifest, manifest_klass, + vmSymbols::object_initializer_name(), + vmSymbols::input_stream_void_signature(), + bais, CHECK_(empty)); + } + atomic_set_shared_jar_manifest(shared_path_index, manifest()); + } + + manifest = Handle(THREAD, shared_jar_manifest(shared_path_index)); + assert(manifest.not_null(), "sanity"); + return manifest; +} + +Handle SystemDictionaryShared::get_shared_jar_url(int shared_path_index, TRAPS) { + Handle url_h; + if (shared_jar_url(shared_path_index) == NULL) { + JavaValue result(T_OBJECT); + const char* path = FileMapInfo::shared_classpath_name(shared_path_index); + Handle path_string = java_lang_String::create_from_str(path, CHECK_(url_h)); + Klass* classLoaders_klass = + SystemDictionary::jdk_internal_loader_ClassLoaders_klass(); + JavaCalls::call_static(&result, classLoaders_klass, + vmSymbols::toFileURL_name(), + vmSymbols::toFileURL_signature(), + path_string, CHECK_(url_h)); + + atomic_set_shared_jar_url(shared_path_index, (oop)result.get_jobject()); + } + + url_h = Handle(THREAD, shared_jar_url(shared_path_index)); + assert(url_h.not_null(), "sanity"); + return url_h; +} + +Handle SystemDictionaryShared::get_package_name(Symbol* class_name, TRAPS) { + ResourceMark rm(THREAD); + Handle pkgname_string; + char* pkgname = (char*) ClassLoader::package_from_name((const char*) class_name->as_C_string()); + if (pkgname != NULL) { // Package prefix found + StringUtils::replace_no_expand(pkgname, "/", "."); + pkgname_string = java_lang_String::create_from_str(pkgname, + CHECK_(pkgname_string)); + } + return pkgname_string; +} + +// Define Package for shared app classes from JAR file and also checks for +// package sealing (all done in Java code) +// See http://docs.oracle.com/javase/tutorial/deployment/jar/sealman.html +void SystemDictionaryShared::define_shared_package(Symbol* class_name, + Handle class_loader, + Handle manifest, + Handle url, + TRAPS) { + assert(class_loader == _java_system_loader, "unexpected class loader"); + // get_package_name() returns a NULL handle if the class is in unnamed package + Handle pkgname_string = get_package_name(class_name, CHECK); + if (pkgname_string.not_null()) { + Klass* app_classLoader_klass = SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass(); + JavaValue result(T_OBJECT); + JavaCallArguments args(3); + args.set_receiver(class_loader); + args.push_oop(pkgname_string); + args.push_oop(manifest); + args.push_oop(url); + JavaCalls::call_virtual(&result, app_classLoader_klass, + vmSymbols::defineOrCheckPackage_name(), + vmSymbols::defineOrCheckPackage_signature(), + &args, + CHECK); + } +} + +// Define Package for shared app/platform classes from named module +void SystemDictionaryShared::define_shared_package(Symbol* class_name, + Handle class_loader, + ModuleEntry* mod_entry, + TRAPS) { + assert(mod_entry != NULL, "module_entry should not be NULL"); + Handle module_handle(THREAD, mod_entry->module()); + + Handle pkg_name = get_package_name(class_name, CHECK); + assert(pkg_name.not_null(), "Package should not be null for class in named module"); + + Klass* classLoader_klass; + if (SystemDictionary::is_system_class_loader(class_loader())) { + classLoader_klass = SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass(); + } else { + assert(SystemDictionary::is_platform_class_loader(class_loader()), "unexpected classloader"); + classLoader_klass = SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass(); + } + + JavaValue result(T_OBJECT); + JavaCallArguments args(2); + args.set_receiver(class_loader); + args.push_oop(pkg_name); + args.push_oop(module_handle); + JavaCalls::call_virtual(&result, classLoader_klass, + vmSymbols::definePackage_name(), + vmSymbols::definePackage_signature(), + &args, + CHECK); +} + +// Get the ProtectionDomain associated with the CodeSource from the classloader. +Handle SystemDictionaryShared::get_protection_domain_from_classloader(Handle class_loader, + Handle url, TRAPS) { + // CodeSource cs = new CodeSource(url, null); + InstanceKlass* cs_klass = SystemDictionary::CodeSource_klass(); + Handle cs = cs_klass->allocate_instance_handle(CHECK_NH); + JavaValue void_result(T_VOID); + JavaCalls::call_special(&void_result, cs, cs_klass, + vmSymbols::object_initializer_name(), + vmSymbols::url_code_signer_array_void_signature(), + url, Handle(), CHECK_NH); + + // protection_domain = SecureClassLoader.getProtectionDomain(cs); + Klass* secureClassLoader_klass = SystemDictionary::SecureClassLoader_klass(); + JavaValue obj_result(T_OBJECT); + JavaCalls::call_virtual(&obj_result, class_loader, secureClassLoader_klass, + vmSymbols::getProtectionDomain_name(), + vmSymbols::getProtectionDomain_signature(), + cs, CHECK_NH); + return Handle(THREAD, (oop)obj_result.get_jobject()); +} + +// Returns the ProtectionDomain associated with the JAR file identified by the url. +Handle SystemDictionaryShared::get_shared_protection_domain(Handle class_loader, + int shared_path_index, + Handle url, + TRAPS) { + Handle protection_domain; + if (shared_protection_domain(shared_path_index) == NULL) { + Handle pd = get_protection_domain_from_classloader(class_loader, url, THREAD); + atomic_set_shared_protection_domain(shared_path_index, pd()); + } + + // Acquire from the cache because if another thread beats the current one to + // set the shared protection_domain and the atomic_set fails, the current thread + // needs to get the updated protection_domain from the cache. + protection_domain = Handle(THREAD, shared_protection_domain(shared_path_index)); + assert(protection_domain.not_null(), "sanity"); + return protection_domain; +} + +// Returns the ProtectionDomain associated with the moduleEntry. +Handle SystemDictionaryShared::get_shared_protection_domain(Handle class_loader, + ModuleEntry* mod, TRAPS) { + ClassLoaderData *loader_data = mod->loader_data(); + Handle protection_domain; + if (mod->shared_protection_domain() == NULL) { + Symbol* location = mod->location(); + if (location != NULL) { + Handle url_string = java_lang_String::create_from_symbol( + location, CHECK_(protection_domain)); + JavaValue result(T_OBJECT); + Klass* classLoaders_klass = + SystemDictionary::jdk_internal_loader_ClassLoaders_klass(); + JavaCalls::call_static(&result, classLoaders_klass, vmSymbols::toFileURL_name(), + vmSymbols::toFileURL_signature(), + url_string, CHECK_(protection_domain)); + Handle url = Handle(THREAD, (oop)result.get_jobject()); + + Handle pd = get_protection_domain_from_classloader(class_loader, url, THREAD); + mod->set_shared_protection_domain(loader_data, pd); + } + } + + protection_domain = Handle(THREAD, mod->shared_protection_domain()); + assert(protection_domain.not_null(), "sanity"); + return protection_domain; +} + +// Initializes the java.lang.Package and java.security.ProtectionDomain objects associated with +// the given InstanceKlass. +// Returns the ProtectionDomain for the InstanceKlass. +Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceKlass* ik, TRAPS) { + Handle pd; + + if (ik != NULL) { + int index = ik->shared_classpath_index(); + assert(index >= 0, "Sanity"); + SharedClassPathEntryExt* ent = + (SharedClassPathEntryExt*)FileMapInfo::shared_classpath(index); + Symbol* class_name = ik->name(); + + if (ent->is_modules_image()) { + // For shared app/platform classes originated from the run-time image: + // The ProtectionDomains are cached in the corresponding ModuleEntries + // for fast access by the VM. + ResourceMark rm; + ClassLoaderData *loader_data = + ClassLoaderData::class_loader_data(class_loader()); + PackageEntryTable* pkgEntryTable = loader_data->packages(); + TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK_(pd)); + if (pkg_name != NULL) { + PackageEntry* pkg_entry = pkgEntryTable->lookup_only(pkg_name); + if (pkg_entry != NULL) { + ModuleEntry* mod_entry = pkg_entry->module(); + pd = get_shared_protection_domain(class_loader, mod_entry, THREAD); + define_shared_package(class_name, class_loader, mod_entry, CHECK_(pd)); + } + } + } else { + // For shared app/platform classes originated from JAR files on the class path: + // Each of the 3 SystemDictionaryShared::_shared_xxx arrays has the same length + // as the shared classpath table in the shared archive (see + // FileMap::_classpath_entry_table in filemap.hpp for details). + // + // If a shared InstanceKlass k is loaded from the class path, let + // + // index = k->shared_classpath_index(): + // + // FileMap::_classpath_entry_table[index] identifies the JAR file that contains k. + // + // k's protection domain is: + // + // ProtectionDomain pd = _shared_protection_domains[index]; + // + // and k's Package is initialized using + // + // manifest = _shared_jar_manifests[index]; + // url = _shared_jar_urls[index]; + // define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd)); + // + // Note that if an element of these 3 _shared_xxx arrays is NULL, it will be initialized by + // the corresponding SystemDictionaryShared::get_shared_xxx() function. + Handle manifest = get_shared_jar_manifest(index, CHECK_(pd)); + Handle url = get_shared_jar_url(index, CHECK_(pd)); + define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd)); + pd = get_shared_protection_domain(class_loader, index, url, CHECK_(pd)); + } + } + return pd; +} + +// Currently AppCDS only archives classes from the run-time image, the +// -Xbootclasspath/a path, and the class path. The following rules need to be +// revised when AppCDS is changed to archive classes from other code sources +// in the future, for example the module path (specified by -p). +// +// Check if a shared class can be loaded by the specific classloader. Following +// are the "visible" archived classes for different classloaders. +// +// NULL classloader: +// - see SystemDictionary::is_shared_class_visible() +// Platform classloader: +// - Module class from "modules" jimage. ModuleEntry must be defined in the +// classloader. +// App Classloader: +// - Module class from "modules" jimage. ModuleEntry must be defined in the +// classloader. +// - Class from -cp. The class must have no PackageEntry defined in any of the +// boot/platform/app classloader, or must be in the unnamed module defined in the +// AppClassLoader. +bool SystemDictionaryShared::is_shared_class_visible_for_classloader( + InstanceKlass* ik, + Handle class_loader, + const char* pkg_string, + Symbol* pkg_name, + PackageEntry* pkg_entry, + ModuleEntry* mod_entry, + TRAPS) { + assert(class_loader.not_null(), "Class loader should not be NULL"); + assert(Universe::is_module_initialized(), "Module system is not initialized"); + + int path_index = ik->shared_classpath_index(); + SharedClassPathEntry* ent = + (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index); + + if (SystemDictionary::is_platform_class_loader(class_loader())) { + assert(ent != NULL, "shared class for PlatformClassLoader should have valid SharedClassPathEntry"); + // The PlatformClassLoader can only load archived class originated from the + // run-time image. The class' PackageEntry/ModuleEntry must be + // defined by the PlatformClassLoader. + if (mod_entry != NULL) { + // PackageEntry/ModuleEntry is found in the classloader. Check if the + // ModuleEntry's location agrees with the archived class' origination. + if (ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) { + return true; // Module class from the "modules" jimage + } + } + } else if (SystemDictionary::is_system_class_loader(class_loader())) { + assert(ent != NULL, "shared class for system loader should have valid SharedClassPathEntry"); + if (pkg_string == NULL) { + // The archived class is in the unnamed package. Currently, the boot image + // does not contain any class in the unnamed package. + assert(!ent->is_modules_image(), "Class in the unnamed package must be from the classpath"); + if (path_index >= ClassLoaderExt::app_paths_start_index()) { + return true; + } + } else { + // Check if this is from a PackageEntry/ModuleEntry defined in the AppClassloader. + if (pkg_entry == NULL) { + // It's not guaranteed that the class is from the classpath if the + // PackageEntry cannot be found from the AppClassloader. Need to check + // the boot and platform classloader as well. + if (get_package_entry(pkg_name, ClassLoaderData::class_loader_data_or_null(SystemDictionary::java_platform_loader())) == NULL && + get_package_entry(pkg_name, ClassLoaderData::the_null_class_loader_data()) == NULL) { + // The PackageEntry is not defined in any of the boot/platform/app classloaders. + // The archived class must from -cp path and not from the run-time image. + if (!ent->is_modules_image() && path_index >= ClassLoaderExt::app_paths_start_index()) { + return true; + } + } + } else if (mod_entry != NULL) { + // The package/module is defined in the AppClassLoader. Currently we only + // support archiving application module class from the run-time image. + // Packages from the -cp path are in the unnamed_module. + if ((ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) || + (pkg_entry->in_unnamed_module() && path_index >= ClassLoaderExt::app_paths_start_index())) { + DEBUG_ONLY( \ + ClassLoaderData* loader_data = class_loader_data(class_loader); \ + if (pkg_entry->in_unnamed_module()) \ + assert(mod_entry == loader_data->unnamed_module(), "the unnamed module is not defined in the classloader");) + + return true; + } + } + } + } else { + // TEMP: if a shared class can be found by a custom loader, consider it visible now. + // FIXME: is this actually correct? + return true; + } + return false; +} + +// The following stack shows how this code is reached: +// +// [0] SystemDictionaryShared::find_or_load_shared_class() +// [1] JVM_FindLoadedClass +// [2] java.lang.ClassLoader.findLoadedClass0() +// [3] java.lang.ClassLoader.findLoadedClass() +// [4] java.lang.ClassLoader.loadClass() +// [5] jdk.internal.loader.ClassLoaders$AppClassLoader_klass.loadClass() +// +// Because AppCDS supports only the PlatformClassLoader and AppClassLoader, we make the following +// assumptions (based on the JDK 8.0 source code): +// +// [a] these two loaders use the default implementation of +// ClassLoader.loadClass(String name, boolean resolve), which +// [b] calls findLoadedClass(name), immediately followed by parent.loadClass(), +// immediately followed by findClass(name). +// [c] If the requested class is a shared class of the current class loader, parent.loadClass() +// always returns null, and +// [d] if AppCDS is not enabled, the class would be loaded by findClass() by decoding it from a +// JAR file and then parsed. +// +// Given these assumptions, we intercept the findLoadedClass() call to invoke +// SystemDictionaryShared::find_or_load_shared_class() to load the shared class from +// the archive. The reasons are: +// +// + Because AppCDS is a commercial feature, we want to hide the implementation. There +// is currently no easy way to hide Java code, so we did it with native code. +// + Start-up is improved because we avoid decoding the JAR file, and avoid delegating +// to the parent (since we know the parent will not find this class). +// +// NOTE: there's a lot of assumption about the Java code. If any of that change, this +// needs to be redesigned. +// +// An alternative is to modify the Java code of AppClassLoader.loadClass(). +// +InstanceKlass* SystemDictionaryShared::find_or_load_shared_class( + Symbol* name, Handle class_loader, TRAPS) { + if (DumpSharedSpaces) { + return NULL; + } + + InstanceKlass* k = NULL; + if (shared_dictionary() != NULL && + UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader()) || + SystemDictionary::is_platform_class_loader(class_loader()))) { + + // Fix for 4474172; see evaluation for more details + class_loader = Handle( + THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader())); + ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL); + Dictionary* dictionary = loader_data->dictionary(); + + unsigned int d_hash = dictionary->compute_hash(name); + + bool DoObjectLock = true; + if (is_parallelCapable(class_loader)) { + DoObjectLock = false; + } + + // Make sure we are synchronized on the class loader before we proceed + // + // Note: currently, find_or_load_shared_class is called only from + // JVM_FindLoadedClass and used for PlatformClassLoader and AppClassLoader, + // which are parallel-capable loaders, so this lock is NOT taken. + Handle lockObject = compute_loader_lock_object(class_loader, THREAD); + check_loader_lock_contention(lockObject, THREAD); + ObjectLocker ol(lockObject, THREAD, DoObjectLock); + + { + MutexLocker mu(SystemDictionary_lock, THREAD); + Klass* check = find_class(d_hash, name, dictionary); + if (check != NULL) { + return InstanceKlass::cast(check); + } + } + + k = load_shared_class_for_builtin_loader(name, class_loader, THREAD); + if (k != NULL) { + define_instance_class(k, CHECK_NULL); + } + } + + return k; +} + +InstanceKlass* SystemDictionaryShared::load_shared_class_for_builtin_loader( + Symbol* class_name, Handle class_loader, TRAPS) { + assert(UseAppCDS && shared_dictionary() != NULL, "already checked"); + Klass* k = shared_dictionary()->find_class_for_builtin_loader(class_name); + + if (k != NULL) { + InstanceKlass* ik = InstanceKlass::cast(k); + if ((ik->is_shared_app_class() && + SystemDictionary::is_system_class_loader(class_loader())) || + (ik->is_shared_platform_class() && + SystemDictionary::is_platform_class_loader(class_loader()))) { + Handle protection_domain = + SystemDictionaryShared::init_security_info(class_loader, ik, CHECK_NULL); + return load_shared_class(ik, class_loader, protection_domain, THREAD); + } + } + + return NULL; +} + +void SystemDictionaryShared::oops_do(OopClosure* f) { + f->do_oop((oop*)&_shared_protection_domains); + f->do_oop((oop*)&_shared_jar_urls); + f->do_oop((oop*)&_shared_jar_manifests); +} + +void SystemDictionaryShared::allocate_shared_protection_domain_array(int size, TRAPS) { + if (_shared_protection_domains == NULL) { + _shared_protection_domains = oopFactory::new_objArray( + SystemDictionary::ProtectionDomain_klass(), size, CHECK); + } +} + +void SystemDictionaryShared::allocate_shared_jar_url_array(int size, TRAPS) { + if (_shared_jar_urls == NULL) { + _shared_jar_urls = oopFactory::new_objArray( + SystemDictionary::URL_klass(), size, CHECK); + } +} + +void SystemDictionaryShared::allocate_shared_jar_manifest_array(int size, TRAPS) { + if (_shared_jar_manifests == NULL) { + _shared_jar_manifests = oopFactory::new_objArray( + SystemDictionary::Jar_Manifest_klass(), size, CHECK); + } +} + +void SystemDictionaryShared::allocate_shared_data_arrays(int size, TRAPS) { + allocate_shared_protection_domain_array(size, CHECK); + allocate_shared_jar_url_array(size, CHECK); + allocate_shared_jar_manifest_array(size, CHECK); +} + + +InstanceKlass* SystemDictionaryShared::lookup_from_stream(const Symbol* class_name, + Handle class_loader, + Handle protection_domain, + const ClassFileStream* cfs, + TRAPS) { + if (!UseAppCDS || shared_dictionary() == NULL) { + return NULL; + } + if (class_name == NULL) { // don't do this for anonymous classes + return NULL; + } + if (class_loader.is_null() || + SystemDictionary::is_system_class_loader(class_loader()) || + SystemDictionary::is_platform_class_loader(class_loader())) { + // This function is called for loading only UNREGISTERED classes. + // Do nothing for the BUILTIN loaders. + return NULL; + } + + ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); + Klass* k; + + { // UNREGISTERED loader + if (!shared_dictionary()->class_exists_for_unregistered_loader(class_name)) { + // No classes of this name for unregistered loaders. + return NULL; + } + + int clsfile_size = cfs->length(); + int clsfile_crc32 = ClassLoader::crc32(0, (const char*)cfs->buffer(), cfs->length()); + + k = shared_dictionary()->find_class_for_unregistered_loader(class_name, + clsfile_size, clsfile_crc32); + } + + if (k == NULL) { // not archived + return NULL; + } + + return acquire_class_for_current_thread(InstanceKlass::cast(k), class_loader, + protection_domain, THREAD); +} + +InstanceKlass* SystemDictionaryShared::acquire_class_for_current_thread( + InstanceKlass *ik, + Handle class_loader, + Handle protection_domain, + TRAPS) { + ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); + + { + MutexLocker mu(SharedDictionary_lock, THREAD); + if (ik->class_loader_data() != NULL) { + // ik is already loaded (by this loader or by a different loader) + // or ik is being loaded by a different thread (by this loader or by a different loader) + return NULL; + } + + // No other thread has acquired this yet, so give it to *this thread* + ik->set_class_loader_data(loader_data); + } + + // No longer holding SharedDictionary_lock + // No need to lock, as can be held only by a single thread. + loader_data->add_class(ik); + + // Load and check super/interfaces, restore unsharable info + InstanceKlass* shared_klass = load_shared_class(ik, class_loader, protection_domain, THREAD); + if (shared_klass == NULL || HAS_PENDING_EXCEPTION) { + // TODO: clean up so it can be used again + return NULL; + } + + return shared_klass; +} + +bool SystemDictionaryShared::add_non_builtin_klass(Symbol* name, ClassLoaderData* loader_data, + InstanceKlass* k, + TRAPS) { + assert(DumpSharedSpaces, "only when dumping"); + assert(UseAppCDS && boot_loader_dictionary() != NULL, "must be"); + + if (boot_loader_dictionary()->add_non_builtin_klass(name, loader_data, k)) { + MutexLocker mu_r(Compile_lock, THREAD); // not really necessary, but add_to_hierarchy asserts this. + add_to_hierarchy(k, CHECK_0); + return true; + } + return false; +} + +// This function is called to resolve the super/interfaces of shared classes for +// non-built-in loaders. E.g., ChildClass in the below example +// where "super:" (and optionally "interface:") have been specified. +// +// java/lang/Object id: 0 +// Interface id: 2 super: 0 source: cust.jar +// ChildClass id: 4 super: 0 interfaces: 2 source: cust.jar +Klass* SystemDictionaryShared::dump_time_resolve_super_or_fail( + Symbol* child_name, Symbol* class_name, Handle class_loader, + Handle protection_domain, bool is_superclass, TRAPS) { + + assert(DumpSharedSpaces, "only when dumping"); + + ClassListParser* parser = ClassListParser::instance(); + if (parser == NULL) { + // We're still loading the well-known classes, before the ClassListParser is created. + return NULL; + } + if (child_name->equals(parser->current_class_name())) { + // When this function is called, all the numbered super and interface types + // must have already been loaded. Hence this function is never recursively called. + if (is_superclass) { + return parser->lookup_super_for_current_class(class_name); + } else { + return parser->lookup_interface_for_current_class(class_name); + } + } else { + // The VM is not trying to resolve a super type of parser->current_class_name(). + // Instead, it's resolving an error class (because parser->current_class_name() has + // failed parsing or verification). Don't do anything here. + return NULL; + } +} + +struct SharedMiscInfo { + Klass* _klass; + int _clsfile_size; + int _clsfile_crc32; +}; + +static GrowableArray* misc_info_array = NULL; + +void SystemDictionaryShared::set_shared_class_misc_info(Klass* k, ClassFileStream* cfs) { + assert(DumpSharedSpaces, "only when dumping"); + int clsfile_size = cfs->length(); + int clsfile_crc32 = ClassLoader::crc32(0, (const char*)cfs->buffer(), cfs->length()); + + if (misc_info_array == NULL) { + misc_info_array = new (ResourceObj::C_HEAP, mtClass) GrowableArray(20, /*c heap*/ true); + } + + SharedMiscInfo misc_info; + DEBUG_ONLY({ + for (int i=0; ilength(); i++) { + misc_info = misc_info_array->at(i); + assert(misc_info._klass != k, "cannot call set_shared_class_misc_info twice for the same class"); + } + }); + + misc_info._klass = k; + misc_info._clsfile_size = clsfile_size; + misc_info._clsfile_crc32 = clsfile_crc32; + + misc_info_array->append(misc_info); +} + +void SystemDictionaryShared::init_shared_dictionary_entry(Klass* k, DictionaryEntry* ent) { + SharedDictionaryEntry* entry = (SharedDictionaryEntry*)ent; + entry->_id = -1; + entry->_clsfile_size = -1; + entry->_clsfile_crc32 = -1; + entry->_verifier_constraints = NULL; + entry->_verifier_constraint_flags = NULL; + + if (misc_info_array != NULL) { + for (int i=0; ilength(); i++) { + SharedMiscInfo misc_info = misc_info_array->at(i); + if (misc_info._klass == k) { + entry->_clsfile_size = misc_info._clsfile_size; + entry->_clsfile_crc32 = misc_info._clsfile_crc32; + misc_info_array->remove_at(i); + return; + } + } + } +} + +bool SystemDictionaryShared::add_verification_constraint(Klass* k, Symbol* name, + Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object) { + assert(DumpSharedSpaces, "called at dump time only"); + + // Skip anonymous classes, which are not archived as they are not in + // dictionary (see assert_no_anonymoys_classes_in_dictionaries() in + // VM_PopulateDumpSharedSpace::doit()). + if (k->class_loader_data()->is_anonymous()) { + return true; // anonymous classes are not archived, skip + } + + SharedDictionaryEntry* entry = ((SharedDictionary*)(k->class_loader_data()->dictionary()))->find_entry_for(k); + ResourceMark rm; + // Lambda classes are not archived and will be regenerated at runtime. + if (entry == NULL && strstr(k->name()->as_C_string(), "Lambda$") != NULL) { + return true; + } + assert(entry != NULL, "class should be in dictionary before being verified"); + entry->add_verification_constraint(name, from_name, from_field_is_protected, + from_is_array, from_is_object); + if (entry->is_builtin()) { + // For builtin class loaders, we can try to complete the verification check at dump time, + // because we can resolve all the constraint classes. + return false; + } else { + // For non-builtin class loaders, we cannot complete the verification check at dump time, + // because at dump time we don't know how to resolve classes for such loaders. + return true; + } +} + +void SystemDictionaryShared::finalize_verification_constraints() { + boot_loader_dictionary()->finalize_verification_constraints(); +} + +void SystemDictionaryShared::check_verification_constraints(InstanceKlass* klass, + TRAPS) { + assert(!DumpSharedSpaces && UseSharedSpaces, "called at run time with CDS enabled only"); + SharedDictionaryEntry* entry = shared_dictionary()->find_entry_for(klass); + assert(entry != NULL, "call this only for shared classes"); + entry->check_verification_constraints(klass, THREAD); +} + +SharedDictionaryEntry* SharedDictionary::find_entry_for(Klass* klass) { + Symbol* class_name = klass->name(); + unsigned int hash = compute_hash(class_name); + int index = hash_to_index(hash); + + for (SharedDictionaryEntry* entry = bucket(index); + entry != NULL; + entry = entry->next()) { + if (entry->hash() == hash && entry->literal() == klass) { + return entry; + } + } + + return NULL; +} + +void SharedDictionary::finalize_verification_constraints() { + int bytes = 0, count = 0; + for (int index = 0; index < table_size(); index++) { + for (SharedDictionaryEntry *probe = bucket(index); + probe != NULL; + probe = probe->next()) { + int n = probe->finalize_verification_constraints(); + if (n > 0) { + bytes += n; + count ++; + } + } + } + if (log_is_enabled(Info, cds, verification)) { + double avg = 0; + if (count > 0) { + avg = double(bytes) / double(count); + } + log_info(cds, verification)("Recorded verification constraints for %d classes = %d bytes (avg = %.2f bytes) ", count, bytes, avg); + } +} + +void SharedDictionaryEntry::add_verification_constraint(Symbol* name, + Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object) { + if (_verifier_constraints == NULL) { + _verifier_constraints = new(ResourceObj::C_HEAP, mtClass) GrowableArray(8, true, mtClass); + } + if (_verifier_constraint_flags == NULL) { + _verifier_constraint_flags = new(ResourceObj::C_HEAP, mtClass) GrowableArray(4, true, mtClass); + } + GrowableArray* vc_array = (GrowableArray*)_verifier_constraints; + for (int i=0; ilength(); i+= 2) { + if (name == vc_array->at(i) && + from_name == vc_array->at(i+1)) { + return; + } + } + vc_array->append(name); + vc_array->append(from_name); + + GrowableArray* vcflags_array = (GrowableArray*)_verifier_constraint_flags; + char c = 0; + c |= from_field_is_protected ? FROM_FIELD_IS_PROTECTED : 0; + c |= from_is_array ? FROM_IS_ARRAY : 0; + c |= from_is_object ? FROM_IS_OBJECT : 0; + vcflags_array->append(c); + + if (log_is_enabled(Trace, cds, verification)) { + ResourceMark rm; + log_trace(cds, verification)("add_verification_constraint: %s: %s must be subclass of %s", + instance_klass()->external_name(), from_name->as_klass_external_name(), + name->as_klass_external_name()); + } +} + +int SharedDictionaryEntry::finalize_verification_constraints() { + assert(DumpSharedSpaces, "called at dump time only"); + Thread* THREAD = Thread::current(); + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + GrowableArray* vc_array = (GrowableArray*)_verifier_constraints; + GrowableArray* vcflags_array = (GrowableArray*)_verifier_constraint_flags; + + if (vc_array != NULL) { + if (log_is_enabled(Trace, cds, verification)) { + ResourceMark rm; + log_trace(cds, verification)("finalize_verification_constraint: %s", + literal()->external_name()); + } + + // Copy the constraints from C_HEAP-alloced GrowableArrays to Metaspace-alloced + // Arrays + int size = 0; + { + // FIXME: change this to be done after relocation, so we can use symbol offset?? + int length = vc_array->length(); + Array* out = MetadataFactory::new_array(loader_data, length, 0, THREAD); + assert(out != NULL, "Dump time allocation failure would have aborted VM"); + for (int i=0; iat_put(i, vc_array->at(i)); + } + _verifier_constraints = out; + size += out->size() * BytesPerWord; + delete vc_array; + } + { + int length = vcflags_array->length(); + Array* out = MetadataFactory::new_array(loader_data, length, 0, THREAD); + assert(out != NULL, "Dump time allocation failure would have aborted VM"); + for (int i=0; iat_put(i, vcflags_array->at(i)); + } + _verifier_constraint_flags = out; + size += out->size() * BytesPerWord; + delete vcflags_array; + } + + return size; + } + return 0; +} + +void SharedDictionaryEntry::check_verification_constraints(InstanceKlass* klass, TRAPS) { + Array* vc_array = (Array*)_verifier_constraints; + Array* vcflags_array = (Array*)_verifier_constraint_flags; + + if (vc_array != NULL) { + int length = vc_array->length(); + for (int i=0; iat(i); + Symbol* from_name = vc_array->at(i+1); + char c = vcflags_array->at(i/2); + + bool from_field_is_protected = (c & FROM_FIELD_IS_PROTECTED) ? true : false; + bool from_is_array = (c & FROM_IS_ARRAY) ? true : false; + bool from_is_object = (c & FROM_IS_OBJECT) ? true : false; + + bool ok = VerificationType::resolve_and_check_assignability(klass, name, + from_name, from_field_is_protected, from_is_array, from_is_object, CHECK); + if (!ok) { + ResourceMark rm(THREAD); + stringStream ss; + + ss.print_cr("Bad type on operand stack"); + ss.print_cr("Exception Details:"); + ss.print_cr(" Location:\n %s", klass->name()->as_C_string()); + ss.print_cr(" Reason:\n Type '%s' is not assignable to '%s'", + from_name->as_quoted_ascii(), name->as_quoted_ascii()); + THROW_MSG(vmSymbols::java_lang_VerifyError(), ss.as_string()); + } + } + } +} + +void SharedDictionaryEntry::metaspace_pointers_do(MetaspaceClosure* it) { + it->push((Array**)&_verifier_constraints); + it->push((Array**)&_verifier_constraint_flags); +} + +bool SharedDictionary::add_non_builtin_klass(const Symbol* class_name, + ClassLoaderData* loader_data, + InstanceKlass* klass) { + + assert(DumpSharedSpaces, "supported only when dumping"); + assert(klass != NULL, "adding NULL klass"); + assert(klass->name() == class_name, "sanity check on name"); + assert(klass->shared_classpath_index() < 0, + "the shared classpath index should not be set for shared class loaded by the custom loaders"); + + // Add an entry for a non-builtin class. + // For a shared class for custom class loaders, SystemDictionary::resolve_or_null will + // not find this class, because is_builtin() is false. + unsigned int hash = compute_hash(class_name); + int index = hash_to_index(hash); + + for (SharedDictionaryEntry* entry = bucket(index); + entry != NULL; + entry = entry->next()) { + if (entry->hash() == hash) { + Klass* klass = (Klass*)entry->literal(); + if (klass->name() == class_name && klass->class_loader_data() == loader_data) { + // There is already a class defined with the same name + return false; + } + } + } + + assert(Dictionary::entry_size() >= sizeof(SharedDictionaryEntry), "must be big enough"); + SharedDictionaryEntry* entry = (SharedDictionaryEntry*)new_entry(hash, klass); + add_entry(index, entry); + + assert(entry->is_unregistered(), "sanity"); + assert(!entry->is_builtin(), "sanity"); + return true; +} + + +//----------------- +// SharedDictionary +//----------------- + + +Klass* SharedDictionary::find_class_for_builtin_loader(const Symbol* name) const { + SharedDictionaryEntry* entry = get_entry_for_builtin_loader(name); + return entry != NULL ? entry->instance_klass() : (Klass*)NULL; +} + +Klass* SharedDictionary::find_class_for_unregistered_loader(const Symbol* name, + int clsfile_size, + int clsfile_crc32) const { + + const SharedDictionaryEntry* entry = get_entry_for_unregistered_loader(name, + clsfile_size, + clsfile_crc32); + return entry != NULL ? entry->instance_klass() : (Klass*)NULL; +} + +void SharedDictionary::update_entry(Klass* klass, int id) { + assert(DumpSharedSpaces, "supported only when dumping"); + Symbol* class_name = klass->name(); + unsigned int hash = compute_hash(class_name); + int index = hash_to_index(hash); + + for (SharedDictionaryEntry* entry = bucket(index); + entry != NULL; + entry = entry->next()) { + if (entry->hash() == hash && entry->literal() == klass) { + entry->_id = id; + return; + } + } + + ShouldNotReachHere(); +} + +SharedDictionaryEntry* SharedDictionary::get_entry_for_builtin_loader(const Symbol* class_name) const { + assert(!DumpSharedSpaces, "supported only when at runtime"); + unsigned int hash = compute_hash(class_name); + const int index = hash_to_index(hash); + + for (SharedDictionaryEntry* entry = bucket(index); + entry != NULL; + entry = entry->next()) { + if (entry->hash() == hash && entry->equals(class_name)) { + if (entry->is_builtin()) { + return entry; + } + } + } + return NULL; +} + +SharedDictionaryEntry* SharedDictionary::get_entry_for_unregistered_loader(const Symbol* class_name, + int clsfile_size, + int clsfile_crc32) const { + assert(!DumpSharedSpaces, "supported only when at runtime"); + unsigned int hash = compute_hash(class_name); + int index = hash_to_index(hash); + + for (SharedDictionaryEntry* entry = bucket(index); + entry != NULL; + entry = entry->next()) { + if (entry->hash() == hash && entry->equals(class_name)) { + if (entry->is_unregistered()) { + if (clsfile_size == -1) { + // We're called from class_exists_for_unregistered_loader. At run time, we want to + // compute the CRC of a ClassFileStream only if there is an UNREGISTERED class + // with the matching name. + return entry; + } else { + // We're called from find_class_for_unregistered_loader + if (entry->_clsfile_size && clsfile_crc32 == entry->_clsfile_crc32) { + return entry; + } + } + + // There can be only 1 class with this name for unregistered loaders. + return NULL; + } + } + } + return NULL; +} diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index 244e98e5d74..c1b87348a5a 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -25,75 +25,362 @@ #ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP #define SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP -#include "classfile/systemDictionary.hpp" +#include "oops/klass.hpp" #include "classfile/dictionary.hpp" +#include "classfile/systemDictionary.hpp" +#include "memory/filemap.hpp" + + +/*=============================================================================== + + Handling of the classes in the AppCDS archive + + To ensure safety and to simplify the implementation, archived classes are + "segregated" into several types. The following rules describe how they + are stored and looked up. + +[1] Category of archived classes + + There are 3 disjoint groups of classes stored in the AppCDS archive. They are + categorized as by their SharedDictionaryEntry::loader_type() + + BUILTIN: These classes may be defined ONLY by the BOOT/PLATFORM/APP + loaders. + + UNREGISTERED: These classes may be defined ONLY by a ClassLoader + instance that's not listed above (using fingerprint matching) + +[2] How classes from different categories are specified in the classlist: + + Starting from JDK9, each class in the classlist may be specified with + these keywords: "id", "super", "interfaces", "loader" and "source". + + + BUILTIN Only the "id" keyword may be (optionally) specified. All other + keywords are forbidden. + + The named class is looked up from the jimage and from + Xbootclasspath/a and CLASSPATH. + + UNREGISTERED: The "id", "super", and "source" keywords must all be + specified. + + The "interfaces" keyword must be specified if the class implements + one or more local interfaces. The "interfaces" keyword must not be + specified if the class does not implement local interfaces. + + The named class is looked up from the location specified in the + "source" keyword. + + Example classlist: + + # BUILTIN + java/lang/Object id: 0 + java/lang/Cloneable id: 1 + java/lang/String + + # UNREGISTERED + Bar id: 3 super: 0 interfaces: 1 source: /foo.jar + + +[3] Identifying the loader_type of archived classes in the shared dictionary + + Each archived Klass* C is associated with a SharedDictionaryEntry* E + + BUILTIN: (C->shared_classpath_index() >= 0) + UNREGISTERED: (C->shared_classpath_index() < 0) + +[4] Lookup of archived classes at run time: + + (a) BUILTIN loaders: + + Search the shared directory for a BUILTIN class with a matching name. + + (b) UNREGISTERED loaders: + + The search originates with SystemDictionaryShared::lookup_from_stream(). + + Search the shared directory for a UNREGISTERED class with a matching + (name, clsfile_len, clsfile_crc32) tuple. + +===============================================================================*/ +#define UNREGISTERED_INDEX -9999 class ClassFileStream; -class SystemDictionaryShared: public SystemDictionary { +// Archived classes need extra information not needed by traditionally loaded classes. +// To keep footprint small, we add these in the dictionary entry instead of the InstanceKlass. +class SharedDictionaryEntry : public DictionaryEntry { + public: - static void initialize(TRAPS) {} - static InstanceKlass* find_or_load_shared_class(Symbol* class_name, - Handle class_loader, - TRAPS) { - return NULL; - } - static void roots_oops_do(OopClosure* blk) {} - static void oops_do(OopClosure* f) {} - static bool is_sharing_possible(ClassLoaderData* loader_data) { - oop class_loader = loader_data->class_loader(); - return (class_loader == NULL); - } - static bool is_shared_class_visible_for_classloader( - InstanceKlass* ik, - Handle class_loader, - const char* pkg_string, - Symbol* pkg_name, - PackageEntry* pkg_entry, - ModuleEntry* mod_entry, - TRAPS) { - return false; + enum LoaderType { + LT_BUILTIN, + LT_UNREGISTERED + }; + + enum { + FROM_FIELD_IS_PROTECTED = 1 << 0, + FROM_IS_ARRAY = 1 << 1, + FROM_IS_OBJECT = 1 << 2 + }; + + int _id; + int _clsfile_size; + int _clsfile_crc32; + void* _verifier_constraints; // FIXME - use a union here to avoid type casting?? + void* _verifier_constraint_flags; + + // See "Identifying the loader_type of archived classes" comments above. + LoaderType loader_type() const { + Klass* k = (Klass*)literal(); + + if ((k->shared_classpath_index() != UNREGISTERED_INDEX)) { + return LT_BUILTIN; + } else { + return LT_UNREGISTERED; + } } + SharedDictionaryEntry* next() { + return (SharedDictionaryEntry*)(DictionaryEntry::next()); + } + + bool is_builtin() const { + return loader_type() == LT_BUILTIN; + } + bool is_unregistered() const { + return loader_type() == LT_UNREGISTERED; + } + + void add_verification_constraint(Symbol* name, + Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object); + int finalize_verification_constraints(); + void check_verification_constraints(InstanceKlass* klass, TRAPS); + void metaspace_pointers_do(MetaspaceClosure* it) NOT_CDS_RETURN; +}; + +class SharedDictionary : public Dictionary { + SharedDictionaryEntry* get_entry_for_builtin_loader(const Symbol* name) const; + SharedDictionaryEntry* get_entry_for_unregistered_loader(const Symbol* name, + int clsfile_size, + int clsfile_crc32) const; + + // Convenience functions + SharedDictionaryEntry* bucket(int index) const { + return (SharedDictionaryEntry*)(Dictionary::bucket(index)); + } + +public: + SharedDictionaryEntry* find_entry_for(Klass* klass); + void finalize_verification_constraints(); + + bool add_non_builtin_klass(const Symbol* class_name, + ClassLoaderData* loader_data, + InstanceKlass* obj); + + void update_entry(Klass* klass, int id); + + Klass* find_class_for_builtin_loader(const Symbol* name) const; + Klass* find_class_for_unregistered_loader(const Symbol* name, + int clsfile_size, + int clsfile_crc32) const; + bool class_exists_for_unregistered_loader(const Symbol* name) { + return (get_entry_for_unregistered_loader(name, -1, -1) != NULL); + } +}; + +class SystemDictionaryShared: public SystemDictionary { +private: + // These _shared_xxxs arrays are used to initialize the java.lang.Package and + // java.security.ProtectionDomain objects associated with each shared class. + // + // See SystemDictionaryShared::init_security_info for more info. + static objArrayOop _shared_protection_domains; + static objArrayOop _shared_jar_urls; + static objArrayOop _shared_jar_manifests; + + static InstanceKlass* load_shared_class_for_builtin_loader( + Symbol* class_name, + Handle class_loader, + TRAPS); + static Handle get_package_name(Symbol* class_name, TRAPS); + + + // Package handling: + // + // 1. For named modules in the runtime image + // BOOT classes: Reuses the existing JVM_GetSystemPackage(s) interfaces + // to get packages in named modules for shared classes. + // Package for non-shared classes in named module is also + // handled using JVM_GetSystemPackage(s). + // + // APP classes: VM calls ClassLoaders.AppClassLoader::definePackage(String, Module) + // to define package for shared app classes from named + // modules. + // + // PLATFORM classes: VM calls ClassLoaders.PlatformClassLoader::definePackage(String, Module) + // to define package for shared platform classes from named + // modules. + // + // 2. For unnamed modules + // BOOT classes: Reuses the existing JVM_GetSystemPackage(s) interfaces to + // get packages for shared boot classes in unnamed modules. + // + // APP classes: VM calls ClassLoaders.AppClassLoader::defineOrCheckPackage() + // with with the manifest and url from archived data. + // + // PLATFORM classes: No package is defined. + // + // The following two define_shared_package() functions are used to define + // package for shared APP and PLATFORM classes. + static void define_shared_package(Symbol* class_name, + Handle class_loader, + Handle manifest, + Handle url, + TRAPS); + static void define_shared_package(Symbol* class_name, + Handle class_loader, + ModuleEntry* mod_entry, + TRAPS); + + static Handle get_shared_jar_manifest(int shared_path_index, TRAPS); + static Handle get_shared_jar_url(int shared_path_index, TRAPS); + static Handle get_protection_domain_from_classloader(Handle class_loader, + Handle url, TRAPS); + static Handle get_shared_protection_domain(Handle class_loader, + int shared_path_index, + Handle url, + TRAPS); + static Handle get_shared_protection_domain(Handle class_loader, + ModuleEntry* mod, TRAPS); + static Handle init_security_info(Handle class_loader, InstanceKlass* ik, TRAPS); + + static void atomic_set_array_index(objArrayOop array, int index, oop o) { + // Benign race condition: array.obj_at(index) may already be filled in. + // The important thing here is that all threads pick up the same result. + // It doesn't matter which racing thread wins, as long as only one + // result is used by all threads, and all future queries. + array->atomic_compare_exchange_oop(index, o, NULL); + } + + static oop shared_protection_domain(int index); + static void atomic_set_shared_protection_domain(int index, oop pd) { + atomic_set_array_index(_shared_protection_domains, index, pd); + } + static void allocate_shared_protection_domain_array(int size, TRAPS); + static oop shared_jar_url(int index); + static void atomic_set_shared_jar_url(int index, oop url) { + atomic_set_array_index(_shared_jar_urls, index, url); + } + static void allocate_shared_jar_url_array(int size, TRAPS); + static oop shared_jar_manifest(int index); + static void atomic_set_shared_jar_manifest(int index, oop man) { + atomic_set_array_index(_shared_jar_manifests, index, man); + } + static void allocate_shared_jar_manifest_array(int size, TRAPS); + static InstanceKlass* acquire_class_for_current_thread( + InstanceKlass *ik, + Handle class_loader, + Handle protection_domain, + TRAPS); + +public: + static void initialize(TRAPS); + + // Called by PLATFORM/APP loader only + static InstanceKlass* find_or_load_shared_class(Symbol* class_name, + Handle class_loader, + TRAPS); + + + static void allocate_shared_data_arrays(int size, TRAPS); + static void oops_do(OopClosure* f); + static void roots_oops_do(OopClosure* f) { + oops_do(f); + } + + // Check if sharing is supported for the class loader. + static bool is_sharing_possible(ClassLoaderData* loader_data) { + oop class_loader = loader_data->class_loader(); + return (class_loader == NULL || + (UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) || + SystemDictionary::is_platform_class_loader(class_loader))) + ); + } + static bool is_shared_class_visible_for_classloader(InstanceKlass* ik, + Handle class_loader, + const char* pkg_string, + Symbol* pkg_name, + PackageEntry* pkg_entry, + ModuleEntry* mod_entry, + TRAPS); + static PackageEntry* get_package_entry(Symbol* pkg, + ClassLoaderData *loader_data) { + if (loader_data != NULL) { + PackageEntryTable* pkgEntryTable = loader_data->packages(); + return pkgEntryTable->lookup_only(pkg); + } + return NULL; + } + + static bool add_non_builtin_klass(Symbol* class_name, ClassLoaderData* loader_data, + InstanceKlass* k, TRAPS); static Klass* dump_time_resolve_super_or_fail(Symbol* child_name, Symbol* class_name, Handle class_loader, Handle protection_domain, bool is_superclass, - TRAPS) { - return NULL; - } + TRAPS); static size_t dictionary_entry_size() { - return sizeof(DictionaryEntry); + return (DumpSharedSpaces) ? sizeof(SharedDictionaryEntry) : sizeof(DictionaryEntry); + } + static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) NOT_CDS_RETURN; + static bool is_builtin(DictionaryEntry* ent) { + // Can't use virtual function is_builtin because DictionaryEntry doesn't initialize + // vtable because it's not constructed properly. + SharedDictionaryEntry* entry = (SharedDictionaryEntry*)ent; + return entry->is_builtin(); } - static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) {} - static bool is_builtin(DictionaryEntry* entry) { return true; } + // For convenient access to the SharedDictionaryEntry's of the archived classes. + static SharedDictionary* shared_dictionary() { + assert(!DumpSharedSpaces, "not for dumping"); + return (SharedDictionary*)SystemDictionary::shared_dictionary(); + } - static InstanceKlass* lookup_from_stream(Symbol* class_name, + static SharedDictionary* boot_loader_dictionary() { + return (SharedDictionary*)ClassLoaderData::the_null_class_loader_data()->dictionary(); + } + + static void update_shared_entry(Klass* klass, int id) { + assert(DumpSharedSpaces, "sanity"); + assert((SharedDictionary*)(klass->class_loader_data()->dictionary()) != NULL, "sanity"); + ((SharedDictionary*)(klass->class_loader_data()->dictionary()))->update_entry(klass, id); + } + + static void set_shared_class_misc_info(Klass* k, ClassFileStream* cfs); + + static InstanceKlass* lookup_from_stream(const Symbol* class_name, Handle class_loader, Handle protection_domain, const ClassFileStream* st, - TRAPS) { - return NULL; - } - - // The (non-application) CDS implementation supports only classes in the boot - // class loader, which ensures that the verification constraints are the same - // during archive creation time and runtime. Thus we can do the constraint checks - // entirely during archive creation time. + TRAPS); + // "verification_constraints" are a set of checks performed by + // VerificationType::is_reference_assignable_from when verifying a shared class during + // dump time. + // + // With AppCDS, it is possible to override archived classes by calling + // ClassLoader.defineClass() directly. SystemDictionary::load_shared_class() already + // ensures that you cannot load a shared class if its super type(s) are changed. However, + // we need an additional check to ensure that the verification_constraints did not change + // between dump time and runtime. static bool add_verification_constraint(Klass* k, Symbol* name, Symbol* from_name, bool from_field_is_protected, - bool from_is_array, bool from_is_object) {return false;} - static void finalize_verification_constraints() {} + bool from_is_array, bool from_is_object) NOT_CDS_RETURN_(false); + static void finalize_verification_constraints() NOT_CDS_RETURN; static void check_verification_constraints(InstanceKlass* klass, - TRAPS) {} -}; - -class SharedDictionaryEntry : public DictionaryEntry { -public: - void metaspace_pointers_do(MetaspaceClosure* it) {} + TRAPS) NOT_CDS_RETURN; }; #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP diff --git a/src/hotspot/share/classfile/systemDictionary_ext.hpp b/src/hotspot/share/classfile/systemDictionary_ext.hpp index 698805b657d..6d257cd09e9 100644 --- a/src/hotspot/share/classfile/systemDictionary_ext.hpp +++ b/src/hotspot/share/classfile/systemDictionary_ext.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017 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,17 @@ #ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP #define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP +#if INCLUDE_CDS + +#define WK_KLASSES_DO_EXT(do_klass) \ + /* well-known classes */ \ + do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \ + /*end*/ + +#else + #define WK_KLASSES_DO_EXT(do_klass) +#endif // INCLUDE_CDS + #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 73fb9296772..65246e04bae 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_CLASSFILE_VMSYMBOLS_HPP #include "classfile/moduleEntry.hpp" -#include "classfile/vmSymbols_ext.hpp" #include "oops/symbol.hpp" #include "memory/iterator.hpp" #include "trace/traceMacros.hpp" @@ -673,8 +672,12 @@ /* trace signatures */ \ TRACE_TEMPLATES(template) \ \ - /* extensions */ \ - VM_SYMBOLS_DO_EXT(template, do_alias) \ + /* cds */ \ + template(jdk_internal_loader_ClassLoaders, "jdk/internal/loader/ClassLoaders") \ + template(jdk_vm_cds_SharedClassInfo, "jdk/vm/cds/SharedClassInfo") \ + template(url_void_signature, "(Ljava/net/URL;)V") \ + template(toFileURL_name, "toFileURL") \ + template(toFileURL_signature, "(Ljava/lang/String;)Ljava/net/URL;") \ \ /*end*/ diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index b49892b1bf0..cf37f8db29c 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -259,12 +259,12 @@ void CodeCache::initialize_heaps() { } // We do not need the profiled CodeHeap, use all space for the non-profiled CodeHeap - if(!heap_available(CodeBlobType::MethodProfiled)) { + if (!heap_available(CodeBlobType::MethodProfiled)) { non_profiled_size += profiled_size; profiled_size = 0; } // We do not need the non-profiled CodeHeap, use all space for the non-nmethod CodeHeap - if(!heap_available(CodeBlobType::MethodNonProfiled)) { + if (!heap_available(CodeBlobType::MethodNonProfiled)) { non_nmethod_size += non_profiled_size; non_profiled_size = 0; } @@ -282,10 +282,11 @@ void CodeCache::initialize_heaps() { FLAG_SET_ERGO(uintx, ProfiledCodeHeapSize, profiled_size); FLAG_SET_ERGO(uintx, NonProfiledCodeHeapSize, non_profiled_size); - // Align CodeHeaps - size_t alignment = heap_alignment(); + // If large page support is enabled, align code heaps according to large + // page size to make sure that code cache is covered by large pages. + const size_t alignment = MAX2(page_size(false), (size_t) os::vm_allocation_granularity()); non_nmethod_size = align_up(non_nmethod_size, alignment); - profiled_size = align_down(profiled_size, alignment); + profiled_size = align_down(profiled_size, alignment); // Reserve one continuous chunk of memory for CodeHeaps and split it into // parts for the individual heaps. The memory layout looks like this: @@ -308,37 +309,29 @@ void CodeCache::initialize_heaps() { add_heap(non_profiled_space, "CodeHeap 'non-profiled nmethods'", CodeBlobType::MethodNonProfiled); } -size_t CodeCache::heap_alignment() { - // If large page support is enabled, align code heaps according to large - // page size to make sure that code cache is covered by large pages. - const size_t page_size = os::can_execute_large_page_memory() ? - os::page_size_for_region_unaligned(ReservedCodeCacheSize, 8) : - os::vm_page_size(); - return MAX2(page_size, (size_t) os::vm_allocation_granularity()); +size_t CodeCache::page_size(bool aligned) { + if (os::can_execute_large_page_memory()) { + return aligned ? os::page_size_for_region_aligned(ReservedCodeCacheSize, 8) : + os::page_size_for_region_unaligned(ReservedCodeCacheSize, 8); + } else { + return os::vm_page_size(); + } } ReservedCodeSpace CodeCache::reserve_heap_memory(size_t size) { - // Determine alignment - const size_t page_size = os::can_execute_large_page_memory() ? - MIN2(os::page_size_for_region_aligned(InitialCodeCacheSize, 8), - os::page_size_for_region_aligned(size, 8)) : - os::vm_page_size(); - const size_t granularity = os::vm_allocation_granularity(); - const size_t r_align = MAX2(page_size, granularity); - const size_t r_size = align_up(size, r_align); - const size_t rs_align = page_size == (size_t) os::vm_page_size() ? 0 : - MAX2(page_size, granularity); - - ReservedCodeSpace rs(r_size, rs_align, rs_align > 0); - + // Align and reserve space for code cache + const size_t rs_ps = page_size(); + const size_t rs_align = MAX2(rs_ps, (size_t) os::vm_allocation_granularity()); + const size_t rs_size = align_up(size, rs_align); + ReservedCodeSpace rs(rs_size, rs_align, rs_ps > (size_t) os::vm_page_size()); if (!rs.is_reserved()) { - vm_exit_during_initialization("Could not reserve enough space for code cache"); + vm_exit_during_initialization(err_msg("Could not reserve enough space for code cache (" SIZE_FORMAT "K)", + rs_size/K)); } // Initialize bounds _low_bound = (address)rs.base(); _high_bound = _low_bound + rs.size(); - return rs; } @@ -415,7 +408,8 @@ void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) size_t size_initial = MIN2(InitialCodeCacheSize, rs.size()); size_initial = align_up(size_initial, os::vm_page_size()); if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) { - vm_exit_during_initialization("Could not reserve enough space for code cache"); + vm_exit_during_initialization(err_msg("Could not reserve enough space in %s (" SIZE_FORMAT "K)", + heap->name(), size_initial/K)); } // Register the CodeHeap diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index 2749acd05b7..e8a098d0279 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -107,7 +107,7 @@ class CodeCache : AllStatic { static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType // Returns the name of the VM option to set the size of the corresponding CodeHeap static const char* get_code_heap_flag_name(int code_blob_type); - static size_t heap_alignment(); // Returns the alignment of the CodeHeaps in bytes + static size_t page_size(bool aligned = true); // Returns the page size used by the CodeCache static ReservedCodeSpace reserve_heap_memory(size_t size); // Reserves one continuous chunk of memory for the CodeHeaps // Iteration diff --git a/src/hotspot/share/code/debugInfo.cpp b/src/hotspot/share/code/debugInfo.cpp index 76a92387528..c81ef90e9d0 100644 --- a/src/hotspot/share/code/debugInfo.cpp +++ b/src/hotspot/share/code/debugInfo.cpp @@ -28,6 +28,8 @@ #include "code/nmethod.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/thread.hpp" // Constructors @@ -209,14 +211,24 @@ void ConstantDoubleValue::print_on(outputStream* st) const { // ConstantOopWriteValue void ConstantOopWriteValue::write_on(DebugInfoWriteStream* stream) { - assert(JNIHandles::resolve(value()) == NULL || - Universe::heap()->is_in_reserved(JNIHandles::resolve(value())), - "Should be in heap"); +#ifdef ASSERT + { + // cannot use ThreadInVMfromNative here since in case of JVMCI compiler, + // thread is already in VM state. + ThreadInVMfromUnknown tiv; + assert(JNIHandles::resolve(value()) == NULL || + Universe::heap()->is_in_reserved(JNIHandles::resolve(value())), + "Should be in heap"); + } +#endif stream->write_int(CONSTANT_OOP_CODE); stream->write_handle(value()); } void ConstantOopWriteValue::print_on(outputStream* st) const { + // using ThreadInVMfromUnknown here since in case of JVMCI compiler, + // thread is already in VM state. + ThreadInVMfromUnknown tiv; JNIHandles::resolve(value())->print_value_on(st); } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 82757c0e2ff..83cc30d79b3 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -438,14 +438,14 @@ nmethod* nmethod::new_native_nmethod(const methodHandle& method, basic_lock_sp_offset, oop_maps); NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); } - // verify nmethod - debug_only(if (nm) nm->verify();) // might block if (nm != NULL) { - nm->log_new_nmethod(); - } + // verify nmethod + debug_only(nm->verify();) // might block - nm->make_in_use(); + nm->log_new_nmethod(); + nm->make_in_use(); + } return nm; } diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 4ac6ab9226d..c2862c84a0b 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -124,7 +124,7 @@ class nmethod : public CompiledMethod { bool _unload_reported; // Protected by Patching_lock - volatile char _state; // {not_installed, in_use, not_entrant, zombie, unloaded} + volatile signed char _state; // {not_installed, in_use, not_entrant, zombie, unloaded} #ifdef ASSERT bool _oops_are_stale; // indicates that it's no longer safe to access oops section diff --git a/src/hotspot/share/code/stubs.cpp b/src/hotspot/share/code/stubs.cpp index 56883bc623d..81717b919ba 100644 --- a/src/hotspot/share/code/stubs.cpp +++ b/src/hotspot/share/code/stubs.cpp @@ -78,7 +78,6 @@ StubQueue::StubQueue(StubInterface* stub_interface, int buffer_size, _queue_begin = 0; _queue_end = 0; _number_of_stubs = 0; - register_queue(this); } @@ -205,36 +204,6 @@ void StubQueue::remove_all(){ } -enum { StubQueueLimit = 10 }; // there are only a few in the world -static StubQueue* registered_stub_queues[StubQueueLimit]; - -void StubQueue::register_queue(StubQueue* sq) { - for (int i = 0; i < StubQueueLimit; i++) { - if (registered_stub_queues[i] == NULL) { - registered_stub_queues[i] = sq; - return; - } - } - ShouldNotReachHere(); -} - - -void StubQueue::queues_do(void f(StubQueue* sq)) { - for (int i = 0; i < StubQueueLimit; i++) { - if (registered_stub_queues[i] != NULL) { - f(registered_stub_queues[i]); - } - } -} - - -void StubQueue::stubs_do(void f(Stub* s)) { - debug_only(verify();) - MutexLockerEx lock(_mutex); - for (Stub* s = first(); s != NULL; s = next(s)) f(s); -} - - void StubQueue::verify() { // verify only if initialized if (_stub_buffer == NULL) return; diff --git a/src/hotspot/share/code/stubs.hpp b/src/hotspot/share/code/stubs.hpp index ab84ffaada9..d50e30d1bd3 100644 --- a/src/hotspot/share/code/stubs.hpp +++ b/src/hotspot/share/code/stubs.hpp @@ -172,8 +172,6 @@ class StubQueue: public CHeapObj { void stub_verify(Stub* s) { _stub_interface->verify(s); } void stub_print(Stub* s) { _stub_interface->print(s); } - static void register_queue(StubQueue*); - public: StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock, const char* name); @@ -204,8 +202,6 @@ class StubQueue: public CHeapObj { void deallocate_unused_tail(); // deallocate the unused tail of the underlying CodeBlob // only used from TemplateInterpreter::initialize() // Iteration - static void queues_do(void f(StubQueue* s)); // call f with each StubQueue - void stubs_do(void f(Stub* s)); // call f with all stubs Stub* first() const { return number_of_stubs() > 0 ? stub_at(_queue_begin) : NULL; } Stub* next(Stub* s) const { int i = index_of(s) + stub_size(s); // Only wrap around in the non-contiguous case (see stubss.cpp) @@ -213,9 +209,6 @@ class StubQueue: public CHeapObj { return (i == _queue_end) ? NULL : stub_at(i); } - address stub_code_begin(Stub* s) const { return _stub_interface->code_begin(s); } - address stub_code_end(Stub* s) const { return _stub_interface->code_end(s); } - // Debugging/printing void verify(); // verifies the stub queue void print(); // prints information about the stub queue diff --git a/src/hotspot/share/compiler/compileTask.hpp b/src/hotspot/share/compiler/compileTask.hpp index c7329c9ba45..3522ee4f10e 100644 --- a/src/hotspot/share/compiler/compileTask.hpp +++ b/src/hotspot/share/compiler/compileTask.hpp @@ -25,10 +25,10 @@ #ifndef SHARE_VM_COMPILER_COMPILETASK_HPP #define SHARE_VM_COMPILER_COMPILETASK_HPP -#include "code/nmethod.hpp" #include "ci/ciMethod.hpp" +#include "code/nmethod.hpp" #include "compiler/compileLog.hpp" -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "utilities/xmlstream.hpp" // CompileTask diff --git a/src/hotspot/share/compiler/methodMatcher.hpp b/src/hotspot/share/compiler/methodMatcher.hpp index 546af4d5ed7..4adf6587417 100644 --- a/src/hotspot/share/compiler/methodMatcher.hpp +++ b/src/hotspot/share/compiler/methodMatcher.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_COMPILER_METHODMATCHER_HPP #define SHARE_VM_COMPILER_METHODMATCHER_HPP -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "runtime/handles.inline.hpp" #include "memory/resourceArea.hpp" diff --git a/src/hotspot/share/compiler/oopMap.hpp b/src/hotspot/share/compiler/oopMap.hpp index 6c9fe4ee299..853f42a6f0d 100644 --- a/src/hotspot/share/compiler/oopMap.hpp +++ b/src/hotspot/share/compiler/oopMap.hpp @@ -28,6 +28,7 @@ #include "code/compressedStream.hpp" #include "code/vmreg.hpp" #include "memory/allocation.hpp" +#include "oops/oopsHierarchy.hpp" #include "utilities/growableArray.hpp" // Interface for generating the frame map for compiled code. A frame map @@ -42,6 +43,7 @@ class frame; class RegisterMap; class DerivedPointerEntry; +class OopClosure; class OopMapValue: public StackObj { friend class VMStructs; diff --git a/src/hotspot/share/gc/cms/allocationStats.cpp b/src/hotspot/share/gc/cms/allocationStats.cpp index f23fa37c313..3bc7074a46e 100644 --- a/src/hotspot/share/gc/cms/allocationStats.cpp +++ b/src/hotspot/share/gc/cms/allocationStats.cpp @@ -30,3 +30,20 @@ // Technically this should be derived from machine speed, and // ideally it would be dynamically adjusted. float AllocationStats::_threshold = ((float)CMS_SweepTimerThresholdMillis)/1000; + +void AllocationStats::initialize(bool split_birth) { + AdaptivePaddedAverage* dummy = + new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight, + CMS_FLSPadding); + _desired = 0; + _coal_desired = 0; + _surplus = 0; + _bfr_surp = 0; + _prev_sweep = 0; + _before_sweep = 0; + _coal_births = 0; + _coal_deaths = 0; + _split_births = (split_birth ? 1 : 0); + _split_deaths = 0; + _returned_bytes = 0; +} diff --git a/src/hotspot/share/gc/cms/allocationStats.hpp b/src/hotspot/share/gc/cms/allocationStats.hpp index 747b2904bed..c98b23f6918 100644 --- a/src/hotspot/share/gc/cms/allocationStats.hpp +++ b/src/hotspot/share/gc/cms/allocationStats.hpp @@ -64,22 +64,7 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC { ssize_t _split_deaths; // loss from splitting size_t _returned_bytes; // number of bytes returned to list. public: - void initialize(bool split_birth = false) { - AdaptivePaddedAverage* dummy = - new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight, - CMS_FLSPadding); - _desired = 0; - _coal_desired = 0; - _surplus = 0; - _bfr_surp = 0; - _prev_sweep = 0; - _before_sweep = 0; - _coal_births = 0; - _coal_deaths = 0; - _split_births = (split_birth ? 1 : 0); - _split_deaths = 0; - _returned_bytes = 0; - } + void initialize(bool split_birth = false); AllocationStats() { initialize(); diff --git a/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp b/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp index 0333b4f433e..e7160fb622a 100644 --- a/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp +++ b/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp @@ -71,6 +71,6 @@ void ConcurrentMarkSweepPolicy::initialize_size_policy(size_t init_eden_size, } void ConcurrentMarkSweepPolicy::initialize_gc_policy_counters() { - // initialize the policy counters - 2 collectors, 3 generations - _gc_policy_counters = new GCPolicyCounters("ParNew:CMS", 2, 3); + // initialize the policy counters - 2 collectors, 2 generations + _gc_policy_counters = new GCPolicyCounters("ParNew:CMS", 2, 2); } diff --git a/src/hotspot/share/gc/cms/cmsHeap.cpp b/src/hotspot/share/gc/cms/cmsHeap.cpp index da344cce24d..8b44d900312 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.cpp +++ b/src/hotspot/share/gc/cms/cmsHeap.cpp @@ -23,17 +23,48 @@ */ #include "precompiled.hpp" +#include "gc/cms/compactibleFreeListSpace.hpp" +#include "gc/cms/concurrentMarkSweepGeneration.hpp" #include "gc/cms/concurrentMarkSweepThread.hpp" #include "gc/cms/cmsHeap.hpp" +#include "gc/cms/parNewGeneration.hpp" #include "gc/cms/vmCMSOperations.hpp" +#include "gc/shared/genMemoryPools.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/workgroup.hpp" #include "oops/oop.inline.hpp" #include "runtime/vmThread.hpp" +#include "services/memoryManager.hpp" #include "utilities/stack.inline.hpp" -CMSHeap::CMSHeap(GenCollectorPolicy *policy) : GenCollectedHeap(policy) { +class CompactibleFreeListSpacePool : public CollectedMemoryPool { +private: + CompactibleFreeListSpace* _space; +public: + CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, + const char* name, + size_t max_size, + bool support_usage_threshold) : + CollectedMemoryPool(name, space->capacity(), max_size, support_usage_threshold), + _space(space) { + } + + MemoryUsage get_memory_usage() { + size_t max_heap_size = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = _space->capacity(); + + return MemoryUsage(initial_size(), used, committed, max_heap_size); + } + + size_t used_in_bytes() { + return _space->used(); + } +}; + +CMSHeap::CMSHeap(GenCollectorPolicy *policy) : + GenCollectedHeap(policy), _eden_pool(NULL), _survivor_pool(NULL), _old_pool(NULL) { _workers = new WorkGang("GC Thread", ParallelGCThreads, /* are_GC_task_threads */true, /* are_ConcurrentGC_threads */false); @@ -54,6 +85,38 @@ jint CMSHeap::initialize() { return JNI_OK; } +void CMSHeap::initialize_serviceability() { + _young_manager = new GCMemoryManager("ParNew", "end of minor GC"); + _old_manager = new GCMemoryManager("ConcurrentMarkSweep", "end of major GC"); + + ParNewGeneration* young = (ParNewGeneration*) young_gen(); + _eden_pool = new ContiguousSpacePool(young->eden(), + "Par Eden Space", + young->max_eden_size(), + false); + + _survivor_pool = new SurvivorContiguousSpacePool(young, + "Par Survivor Space", + young->max_survivor_size(), + false); + + ConcurrentMarkSweepGeneration* old = (ConcurrentMarkSweepGeneration*) old_gen(); + _old_pool = new CompactibleFreeListSpacePool(old->cmsSpace(), + "CMS Old Gen", + old->reserved().byte_size(), + true); + + _young_manager->add_pool(_eden_pool); + _young_manager->add_pool(_survivor_pool); + young->set_gc_manager(_young_manager); + + _old_manager->add_pool(_eden_pool); + _old_manager->add_pool(_survivor_pool); + _old_manager->add_pool(_old_pool); + old ->set_gc_manager(_old_manager); + +} + void CMSHeap::check_gen_kinds() { assert(young_gen()->kind() == Generation::ParNew, "Wrong youngest generation type"); @@ -183,3 +246,18 @@ void CMSHeap::gc_epilogue(bool full) { GenCollectedHeap::gc_epilogue(full); always_do_update_barrier = true; }; + +GrowableArray CMSHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(_young_manager); + memory_managers.append(_old_manager); + return memory_managers; +} + +GrowableArray CMSHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} diff --git a/src/hotspot/share/gc/cms/cmsHeap.hpp b/src/hotspot/share/gc/cms/cmsHeap.hpp index bcd30cba859..93079d7cf2b 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.hpp +++ b/src/hotspot/share/gc/cms/cmsHeap.hpp @@ -29,9 +29,12 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/genCollectedHeap.hpp" +#include "utilities/growableArray.hpp" class CLDClosure; class GenCollectorPolicy; +class GCMemoryManager; +class MemoryPool; class OopsInGenClosure; class outputStream; class StrongRootsScope; @@ -80,6 +83,9 @@ public: void safepoint_synchronize_begin(); void safepoint_synchronize_end(); + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + // If "young_gen_as_roots" is false, younger generations are // not scanned as roots; in this case, the caller must be arranging to // scan the younger generations itself. (For example, a generation might @@ -92,12 +98,19 @@ public: OopsInGenClosure* root_closure, CLDClosure* cld_closure); + GCMemoryManager* old_manager() const { return _old_manager; } + private: WorkGang* _workers; + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); + virtual void initialize_serviceability(); + // Accessor for memory state verification support NOT_PRODUCT( virtual size_t skip_header_HeapWords() { return CMSCollector::skip_header_HeapWords(); } diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index c49112957b0..4f8f7836550 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -8116,42 +8116,42 @@ size_t MarkDeadObjectsClosure::do_blk(HeapWord* addr) { } TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase, GCCause::Cause cause): TraceMemoryManagerStats() { - + GCMemoryManager* manager = CMSHeap::heap()->old_manager(); switch (phase) { case CMSCollector::InitialMarking: - initialize(true /* fullGC */ , - cause /* cause of the GC */, - true /* recordGCBeginTime */, - true /* recordPreGCUsage */, - false /* recordPeakUsage */, - false /* recordPostGCusage */, - true /* recordAccumulatedGCTime */, - false /* recordGCEndTime */, - false /* countCollection */ ); + initialize(manager /* GC manager */ , + cause /* cause of the GC */, + true /* recordGCBeginTime */, + true /* recordPreGCUsage */, + false /* recordPeakUsage */, + false /* recordPostGCusage */, + true /* recordAccumulatedGCTime */, + false /* recordGCEndTime */, + false /* countCollection */ ); break; case CMSCollector::FinalMarking: - initialize(true /* fullGC */ , - cause /* cause of the GC */, - false /* recordGCBeginTime */, - false /* recordPreGCUsage */, - false /* recordPeakUsage */, - false /* recordPostGCusage */, - true /* recordAccumulatedGCTime */, - false /* recordGCEndTime */, - false /* countCollection */ ); + initialize(manager /* GC manager */ , + cause /* cause of the GC */, + false /* recordGCBeginTime */, + false /* recordPreGCUsage */, + false /* recordPeakUsage */, + false /* recordPostGCusage */, + true /* recordAccumulatedGCTime */, + false /* recordGCEndTime */, + false /* countCollection */ ); break; case CMSCollector::Sweeping: - initialize(true /* fullGC */ , - cause /* cause of the GC */, - false /* recordGCBeginTime */, - false /* recordPreGCUsage */, - true /* recordPeakUsage */, - true /* recordPostGCusage */, - false /* recordAccumulatedGCTime */, - true /* recordGCEndTime */, - true /* countCollection */ ); + initialize(manager /* GC manager */ , + cause /* cause of the GC */, + false /* recordGCBeginTime */, + false /* recordPreGCUsage */, + true /* recordPeakUsage */, + true /* recordPostGCusage */, + false /* recordAccumulatedGCTime */, + true /* recordGCEndTime */, + true /* countCollection */ ); break; default: diff --git a/src/hotspot/share/gc/cms/gSpaceCounters.cpp b/src/hotspot/share/gc/cms/gSpaceCounters.cpp index dce1f39f6d5..36776c52945 100644 --- a/src/hotspot/share/gc/cms/gSpaceCounters.cpp +++ b/src/hotspot/share/gc/cms/gSpaceCounters.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc/cms/gSpaceCounters.hpp" #include "gc/shared/generation.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "utilities/macros.hpp" @@ -71,3 +72,7 @@ GSpaceCounters::GSpaceCounters(const char* name, int ordinal, size_t max_size, _gen->capacity(), CHECK); } } + +GSpaceCounters::~GSpaceCounters() { + if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); +} diff --git a/src/hotspot/share/gc/cms/gSpaceCounters.hpp b/src/hotspot/share/gc/cms/gSpaceCounters.hpp index 64ae6c60b26..40f181f4c4c 100644 --- a/src/hotspot/share/gc/cms/gSpaceCounters.hpp +++ b/src/hotspot/share/gc/cms/gSpaceCounters.hpp @@ -52,9 +52,7 @@ class GSpaceCounters: public CHeapObj { GSpaceCounters(const char* name, int ordinal, size_t max_size, Generation* g, GenerationCounters* gc, bool sampled=true); - ~GSpaceCounters() { - if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); - } + ~GSpaceCounters(); inline void update_capacity() { _capacity->set_value(_gen->capacity()); diff --git a/src/hotspot/share/gc/g1/dirtyCardQueue.cpp b/src/hotspot/share/gc/g1/dirtyCardQueue.cpp index 11c2da764e4..ae6a476ff59 100644 --- a/src/hotspot/share/gc/g1/dirtyCardQueue.cpp +++ b/src/hotspot/share/gc/g1/dirtyCardQueue.cpp @@ -32,6 +32,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" // Closure used for updating remembered sets and recording references that // point into the collection set while the mutator is running. @@ -319,7 +320,7 @@ void DirtyCardQueueSet::abandon_logs() { clear(); // Since abandon is done only at safepoints, we can safely manipulate // these queues. - for (JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { t->dirty_card_queue().reset(); } shared_dirty_card_queue()->reset(); @@ -338,7 +339,7 @@ void DirtyCardQueueSet::concatenate_logs() { int save_max_completed_queue = _max_completed_queue; _max_completed_queue = max_jint; assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); - for (JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { concatenate_log(t->dirty_card_queue()); } concatenate_log(_shared_dirty_card_queue); diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp index bfe27a1cfae..b9ad5a02951 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -26,6 +26,7 @@ #include "gc/g1/g1Arguments.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/heapRegion.hpp" #include "gc/shared/gcArguments.inline.hpp" #include "runtime/globals.hpp" @@ -92,6 +93,22 @@ void G1Arguments::initialize_flags() { } log_trace(gc)("MarkStackSize: %uk MarkStackSizeMax: %uk", (unsigned int) (MarkStackSize / K), (uint) (MarkStackSizeMax / K)); + +#ifdef COMPILER2 + // Enable loop strip mining to offer better pause time guarantees + if (FLAG_IS_DEFAULT(UseCountedLoopSafepoints)) { + FLAG_SET_DEFAULT(UseCountedLoopSafepoints, true); + } + if (UseCountedLoopSafepoints && FLAG_IS_DEFAULT(LoopStripMiningIter)) { + FLAG_SET_DEFAULT(LoopStripMiningIter, 1000); + } +#endif +} + +bool G1Arguments::parse_verification_type(const char* type) { + G1CollectedHeap::heap()->verifier()->parse_verification_type(type); + // Always return true because we want to parse all values. + return true; } CollectedHeap* G1Arguments::create_heap() { diff --git a/src/hotspot/share/gc/g1/g1Arguments.hpp b/src/hotspot/share/gc/g1/g1Arguments.hpp index 3f87c638c49..2dd753eb2a5 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.hpp +++ b/src/hotspot/share/gc/g1/g1Arguments.hpp @@ -32,6 +32,7 @@ class CollectedHeap; class G1Arguments : public GCArguments { public: virtual void initialize_flags(); + virtual bool parse_verification_type(const char* type); virtual size_t conservative_max_heap_alignment(); virtual CollectedHeap* create_heap(); }; diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index a62a48eeac5..7245bf55388 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -39,12 +39,12 @@ #include "gc/g1/g1ConcurrentRefineThread.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1FullCollector.hpp" -#include "gc/g1/g1FullGCScope.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1HotCardCache.hpp" +#include "gc/g1/g1MemoryPool.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1Policy.hpp" @@ -81,6 +81,7 @@ #include "runtime/atomic.hpp" #include "runtime/init.hpp" #include "runtime/orderAccess.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vmThread.hpp" #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" @@ -1083,7 +1084,6 @@ void G1CollectedHeap::print_hrm_post_compaction() { PostCompactionPrinterClosure cl(hr_printer()); heap_region_iterate(&cl); } - } void G1CollectedHeap::abort_concurrent_cycle() { @@ -1132,7 +1132,7 @@ void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) { assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant"); assert(used() == recalculate_used(), "Should be equal"); _verifier->verify_region_sets_optional(); - _verifier->verify_before_gc(); + _verifier->verify_before_gc(G1HeapVerifier::G1VerifyFull); _verifier->check_bitmaps("Full GC Start"); } @@ -1173,7 +1173,7 @@ void G1CollectedHeap::verify_after_full_collection() { check_gc_time_stamps(); _hrm.verify_optional(); _verifier->verify_region_sets_optional(); - _verifier->verify_after_gc(); + _verifier->verify_after_gc(G1HeapVerifier::G1VerifyFull); // Clear the previous marking bitmap, if needed for bitmap verification. // Note we cannot do this when we clear the next marking bitmap in // G1ConcurrentMark::abort() above since VerifyDuringGC verifies the @@ -1217,34 +1217,6 @@ void G1CollectedHeap::print_heap_after_full_collection(G1HeapTransition* heap_tr #endif } -void G1CollectedHeap::do_full_collection_inner(G1FullGCScope* scope) { - GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true); - g1_policy()->record_full_collection_start(); - - print_heap_before_gc(); - print_heap_regions(); - - abort_concurrent_cycle(); - verify_before_full_collection(scope->is_explicit_gc()); - - gc_prologue(true); - prepare_heap_for_full_collection(); - - G1FullCollector collector(scope, ref_processor_stw(), concurrent_mark()->next_mark_bitmap(), workers()->active_workers()); - collector.prepare_collection(); - collector.collect(); - collector.complete_collection(); - - prepare_heap_for_mutators(); - - g1_policy()->record_full_collection_end(); - gc_epilogue(true); - - verify_after_full_collection(); - - print_heap_after_full_collection(scope->heap_transition()); -} - bool G1CollectedHeap::do_full_collection(bool explicit_gc, bool clear_all_soft_refs) { assert_at_safepoint(true /* should_be_vm_thread */); @@ -1257,8 +1229,12 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, const bool do_clear_all_soft_refs = clear_all_soft_refs || collector_policy()->should_clear_all_soft_refs(); - G1FullGCScope scope(explicit_gc, do_clear_all_soft_refs); - do_full_collection_inner(&scope); + G1FullCollector collector(this, &_full_gc_memory_manager, explicit_gc, do_clear_all_soft_refs); + GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true); + + collector.prepare_collection(); + collector.collect(); + collector.complete_collection(); // Full collection was successfully completed. return true; @@ -1550,6 +1526,11 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) : CollectedHeap(), _young_gen_sampling_thread(NULL), _collector_policy(collector_policy), + _memory_manager("G1 Young Generation", "end of minor GC"), + _full_gc_memory_manager("G1 Old Generation", "end of major GC"), + _eden_pool(NULL), + _survivor_pool(NULL), + _old_pool(NULL), _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()), _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()), _g1_policy(create_g1_policy(_gc_timer_stw)), @@ -1854,6 +1835,20 @@ jint G1CollectedHeap::initialize() { return JNI_OK; } +void G1CollectedHeap::initialize_serviceability() { + _eden_pool = new G1EdenPool(this); + _survivor_pool = new G1SurvivorPool(this); + _old_pool = new G1OldGenPool(this); + + _full_gc_memory_manager.add_pool(_eden_pool); + _full_gc_memory_manager.add_pool(_survivor_pool); + _full_gc_memory_manager.add_pool(_old_pool); + + _memory_manager.add_pool(_eden_pool); + _memory_manager.add_pool(_survivor_pool); + +} + void G1CollectedHeap::stop() { // Stop all concurrent threads. We do this to make sure these threads // do not continue to execute and access resources (e.g. logging) @@ -1879,6 +1874,7 @@ size_t G1CollectedHeap::conservative_max_heap_alignment() { } void G1CollectedHeap::post_initialize() { + CollectedHeap::post_initialize(); ref_processing_init(); } @@ -2653,11 +2649,9 @@ G1CollectedHeap::doConcurrentMark() { size_t G1CollectedHeap::pending_card_num() { size_t extra_cards = 0; - JavaThread *curr = Threads::first(); - while (curr != NULL) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *curr = jtiwh.next(); ) { DirtyCardQueue& dcq = curr->dirty_card_queue(); extra_cards += dcq.size(); - curr = curr->next(); } DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); size_t buffer_size = dcqs.buffer_size(); @@ -2963,13 +2957,17 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { GCTraceCPUTime tcpu; + G1HeapVerifier::G1VerifyType verify_type; FormatBuffer<> gc_string("Pause "); if (collector_state()->during_initial_mark_pause()) { gc_string.append("Initial Mark"); + verify_type = G1HeapVerifier::G1VerifyInitialMark; } else if (collector_state()->gcs_are_young()) { gc_string.append("Young"); + verify_type = G1HeapVerifier::G1VerifyYoungOnly; } else { gc_string.append("Mixed"); + verify_type = G1HeapVerifier::G1VerifyMixed; } GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true); @@ -2980,7 +2978,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers()->total_workers()); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); - TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); + TraceMemoryManagerStats tms(&_memory_manager, gc_cause()); // If the secondary_free_list is not empty, append it to the // free_list. No need to wait for the cleanup operation to finish; @@ -3010,7 +3008,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { heap_region_iterate(&v_cl); } - _verifier->verify_before_gc(); + _verifier->verify_before_gc(verify_type); _verifier->check_bitmaps("GC Start"); @@ -3170,7 +3168,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { heap_region_iterate(&v_cl); } - _verifier->verify_after_gc(); + _verifier->verify_after_gc(verify_type); _verifier->check_bitmaps("GC End"); assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); @@ -5394,3 +5392,18 @@ void G1CollectedHeap::rebuild_strong_code_roots() { RebuildStrongCodeRootClosure blob_cl(this); CodeCache::blobs_do(&blob_cl); } + +GrowableArray G1CollectedHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(&_memory_manager); + memory_managers.append(&_full_gc_memory_manager); + return memory_managers; +} + +GrowableArray G1CollectedHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 7467a5493f9..d268e2ef7be 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -42,14 +42,15 @@ #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/g1SurvivorRegions.hpp" #include "gc/g1/g1YCTypes.hpp" -#include "gc/g1/hSpaceCounters.hpp" #include "gc/g1/heapRegionManager.hpp" #include "gc/g1/heapRegionSet.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/gcHeapSummary.hpp" #include "gc/shared/plab.hpp" #include "gc/shared/preservedMarks.hpp" #include "memory/memRegion.hpp" +#include "services/memoryManager.hpp" #include "utilities/stack.hpp" // A "G1CollectedHeap" is an implementation of a java heap for HotSpot. @@ -64,6 +65,7 @@ class GenerationSpec; class G1ParScanThreadState; class G1ParScanThreadStateSet; class G1ParScanThreadState; +class MemoryPool; class ObjectClosure; class SpaceClosure; class CompactibleSpaceClosure; @@ -126,6 +128,7 @@ class G1CollectedHeap : public CollectedHeap { friend class VM_G1IncCollectionPause; friend class VMStructs; friend class MutatorAllocRegion; + friend class G1FullCollector; friend class G1GCAllocRegion; friend class G1HeapVerifier; @@ -148,6 +151,13 @@ private: WorkGang* _workers; G1CollectorPolicy* _collector_policy; + GCMemoryManager _memory_manager; + GCMemoryManager _full_gc_memory_manager; + + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; + static size_t _humongous_object_threshold_in_words; // The secondary free list which contains regions that have been @@ -161,6 +171,8 @@ private: // It keeps track of the humongous regions. HeapRegionSet _humongous_set; + virtual void initialize_serviceability(); + void eagerly_reclaim_humongous_regions(); // Start a new incremental collection set for the next pause. void start_new_collection_set(); @@ -517,7 +529,6 @@ protected: private: // Internal helpers used during full GC to split it up to // increase readability. - void do_full_collection_inner(G1FullGCScope* scope); void abort_concurrent_cycle(); void verify_before_full_collection(bool explicit_gc); void prepare_heap_for_full_collection(); @@ -1006,6 +1017,9 @@ public: // Adaptive size policy. No such thing for g1. virtual AdaptiveSizePolicy* size_policy() { return NULL; } + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + // The rem set and barrier set. G1RemSet* g1_rem_set() const { return _g1_rem_set; } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 9073616c33f..a63013bdec4 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1015,9 +1015,7 @@ void G1ConcurrentMark::checkpoint_roots_final(bool clear_all_soft_refs) { SvcGCMarker sgcm(SvcGCMarker::OTHER); if (VerifyDuringGC) { - HandleMark hm; // handle scope - g1h->prepare_for_verify(); - Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (before)"); + g1h->verifier()->verify(G1HeapVerifier::G1VerifyRemark, VerifyOption_G1UsePrevMarking, "During GC (before)"); } g1h->verifier()->check_bitmaps("Remark Start"); @@ -1038,9 +1036,7 @@ void G1ConcurrentMark::checkpoint_roots_final(bool clear_all_soft_refs) { // Verify the heap w.r.t. the previous marking bitmap. if (VerifyDuringGC) { - HandleMark hm; // handle scope - g1h->prepare_for_verify(); - Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (overflow)"); + g1h->verifier()->verify(G1HeapVerifier::G1VerifyRemark, VerifyOption_G1UsePrevMarking, "During GC (overflow)"); } // Clear the marking state because we will be restarting @@ -1055,9 +1051,7 @@ void G1ConcurrentMark::checkpoint_roots_final(bool clear_all_soft_refs) { true /* expected_active */); if (VerifyDuringGC) { - HandleMark hm; // handle scope - g1h->prepare_for_verify(); - Universe::verify(VerifyOption_G1UseNextMarking, "During GC (after)"); + g1h->verifier()->verify(G1HeapVerifier::G1VerifyRemark, VerifyOption_G1UseNextMarking, "During GC (after)"); } g1h->verifier()->check_bitmaps("Remark End"); assert(!restart_for_overflow(), "sanity"); @@ -1189,9 +1183,7 @@ void G1ConcurrentMark::cleanup() { g1h->verifier()->verify_region_sets_optional(); if (VerifyDuringGC) { - HandleMark hm; // handle scope - g1h->prepare_for_verify(); - Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (before)"); + g1h->verifier()->verify(G1HeapVerifier::G1VerifyCleanup, VerifyOption_G1UsePrevMarking, "During GC (before)"); } g1h->verifier()->check_bitmaps("Cleanup Start"); @@ -1263,9 +1255,7 @@ void G1ConcurrentMark::cleanup() { Universe::update_heap_info_at_gc(); if (VerifyDuringGC) { - HandleMark hm; // handle scope - g1h->prepare_for_verify(); - Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (after)"); + g1h->verifier()->verify(G1HeapVerifier::G1VerifyCleanup, VerifyOption_G1UsePrevMarking, "During GC (after)"); } g1h->verifier()->check_bitmaps("Cleanup End"); @@ -1756,28 +1746,24 @@ private: G1ConcurrentMark* _cm; public: void work(uint worker_id) { - // Since all available tasks are actually started, we should - // only proceed if we're supposed to be active. - if (worker_id < _cm->active_tasks()) { - G1CMTask* task = _cm->task(worker_id); - task->record_start_time(); - { - ResourceMark rm; - HandleMark hm; + G1CMTask* task = _cm->task(worker_id); + task->record_start_time(); + { + ResourceMark rm; + HandleMark hm; - G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task); - Threads::threads_do(&threads_f); - } - - do { - task->do_marking_step(1000000000.0 /* something very large */, - true /* do_termination */, - false /* is_serial */); - } while (task->has_aborted() && !_cm->has_overflown()); - // If we overflow, then we do not want to restart. We instead - // want to abort remark and do concurrent marking again. - task->record_end_time(); + G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task); + Threads::threads_do(&threads_f); } + + do { + task->do_marking_step(1000000000.0 /* something very large */, + true /* do_termination */, + false /* is_serial */); + } while (task->has_aborted() && !_cm->has_overflown()); + // If we overflow, then we do not want to restart. We instead + // want to abort remark and do concurrent marking again. + task->record_end_time(); } G1CMRemarkTask(G1ConcurrentMark* cm, uint active_workers) : diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index 8e39ff06698..31d09e9428b 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -26,6 +26,7 @@ #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" #include "logging/log.hpp" +#include "memory/allocation.inline.hpp" #include "runtime/java.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" @@ -33,6 +34,107 @@ #include "utilities/pair.hpp" #include +G1ConcurrentRefineThread* G1ConcurrentRefineThreadControl::create_refinement_thread(uint worker_id, bool initializing) { + G1ConcurrentRefineThread* result = NULL; + if (initializing || !InjectGCWorkerCreationFailure) { + result = new G1ConcurrentRefineThread(_cr, worker_id); + } + if (result == NULL || result->osthread() == NULL) { + log_warning(gc)("Failed to create refinement thread %u, no more %s", + worker_id, + result == NULL ? "memory" : "OS threads"); + } + return result; +} + +G1ConcurrentRefineThreadControl::G1ConcurrentRefineThreadControl() : + _cr(NULL), + _threads(NULL), + _num_max_threads(0) +{ +} + +G1ConcurrentRefineThreadControl::~G1ConcurrentRefineThreadControl() { + for (uint i = 0; i < _num_max_threads; i++) { + G1ConcurrentRefineThread* t = _threads[i]; + if (t != NULL) { + delete t; + } + } + FREE_C_HEAP_ARRAY(G1ConcurrentRefineThread*, _threads); +} + +jint G1ConcurrentRefineThreadControl::initialize(G1ConcurrentRefine* cr, uint num_max_threads) { + assert(cr != NULL, "G1ConcurrentRefine must not be NULL"); + _cr = cr; + _num_max_threads = num_max_threads; + + _threads = NEW_C_HEAP_ARRAY_RETURN_NULL(G1ConcurrentRefineThread*, num_max_threads, mtGC); + if (_threads == NULL) { + vm_shutdown_during_initialization("Could not allocate thread holder array."); + return JNI_ENOMEM; + } + + for (uint i = 0; i < num_max_threads; i++) { + if (UseDynamicNumberOfGCThreads && i != 0 /* Always start first thread. */) { + _threads[i] = NULL; + } else { + _threads[i] = create_refinement_thread(i, true); + if (_threads[i] == NULL) { + vm_shutdown_during_initialization("Could not allocate refinement threads."); + return JNI_ENOMEM; + } + } + } + return JNI_OK; +} + +void G1ConcurrentRefineThreadControl::maybe_activate_next(uint cur_worker_id) { + assert(cur_worker_id < _num_max_threads, + "Activating another thread from %u not allowed since there can be at most %u", + cur_worker_id, _num_max_threads); + if (cur_worker_id == (_num_max_threads - 1)) { + // Already the last thread, there is no more thread to activate. + return; + } + + uint worker_id = cur_worker_id + 1; + G1ConcurrentRefineThread* thread_to_activate = _threads[worker_id]; + if (thread_to_activate == NULL) { + // Still need to create the thread... + _threads[worker_id] = create_refinement_thread(worker_id, false); + thread_to_activate = _threads[worker_id]; + } + if (thread_to_activate != NULL && !thread_to_activate->is_active()) { + thread_to_activate->activate(); + } +} + +void G1ConcurrentRefineThreadControl::print_on(outputStream* st) const { + for (uint i = 0; i < _num_max_threads; ++i) { + if (_threads[i] != NULL) { + _threads[i]->print_on(st); + st->cr(); + } + } +} + +void G1ConcurrentRefineThreadControl::worker_threads_do(ThreadClosure* tc) { + for (uint i = 0; i < _num_max_threads; i++) { + if (_threads[i] != NULL) { + tc->do_thread(_threads[i]); + } + } +} + +void G1ConcurrentRefineThreadControl::stop() { + for (uint i = 0; i < _num_max_threads; i++) { + if (_threads[i] != NULL) { + _threads[i]->stop(); + } + } +} + // Arbitrary but large limits, to simplify some of the zone calculations. // The general idea is to allow expressions like // MIN2(x OP y, max_XXX_zone) @@ -96,7 +198,7 @@ static Thresholds calc_thresholds(size_t green_zone, size_t yellow_zone, uint worker_i) { double yellow_size = yellow_zone - green_zone; - double step = yellow_size / G1ConcurrentRefine::thread_num(); + double step = yellow_size / G1ConcurrentRefine::max_num_threads(); if (worker_i == 0) { // Potentially activate worker 0 more aggressively, to keep // available buffers near green_zone value. When yellow_size is @@ -115,8 +217,7 @@ G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone, size_t yellow_zone, size_t red_zone, size_t min_yellow_zone_size) : - _threads(NULL), - _n_worker_threads(thread_num()), + _thread_control(), _green_zone(green_zone), _yellow_zone(yellow_zone), _red_zone(red_zone), @@ -125,9 +226,13 @@ G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone, assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone); } +jint G1ConcurrentRefine::initialize() { + return _thread_control.initialize(this, max_num_threads()); +} + static size_t calc_min_yellow_zone_size() { size_t step = G1ConcRefinementThresholdStep; - uint n_workers = G1ConcurrentRefine::thread_num(); + uint n_workers = G1ConcurrentRefine::max_num_threads(); if ((max_yellow_zone / step) < n_workers) { return max_yellow_zone; } else { @@ -191,77 +296,27 @@ G1ConcurrentRefine* G1ConcurrentRefine::create(jint* ecode) { return NULL; } - cr->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(G1ConcurrentRefineThread*, cr->_n_worker_threads, mtGC); - if (cr->_threads == NULL) { - *ecode = JNI_ENOMEM; - vm_shutdown_during_initialization("Could not allocate an array for G1ConcurrentRefineThread"); - return NULL; - } - - uint worker_id_offset = DirtyCardQueueSet::num_par_ids(); - - G1ConcurrentRefineThread *next = NULL; - for (uint i = cr->_n_worker_threads - 1; i != UINT_MAX; i--) { - Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i); - G1ConcurrentRefineThread* t = - new G1ConcurrentRefineThread(cr, - next, - worker_id_offset, - i, - activation_level(thresholds), - deactivation_level(thresholds)); - assert(t != NULL, "Conc refine should have been created"); - if (t->osthread() == NULL) { - *ecode = JNI_ENOMEM; - vm_shutdown_during_initialization("Could not create G1ConcurrentRefineThread"); - return NULL; - } - - assert(t->cr() == cr, "Conc refine thread should refer to this"); - cr->_threads[i] = t; - next = t; - } - - *ecode = JNI_OK; + *ecode = cr->initialize(); return cr; } void G1ConcurrentRefine::stop() { - for (uint i = 0; i < _n_worker_threads; i++) { - _threads[i]->stop(); - } -} - -void G1ConcurrentRefine::update_thread_thresholds() { - for (uint i = 0; i < _n_worker_threads; i++) { - Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, i); - _threads[i]->update_thresholds(activation_level(thresholds), - deactivation_level(thresholds)); - } + _thread_control.stop(); } G1ConcurrentRefine::~G1ConcurrentRefine() { - for (uint i = 0; i < _n_worker_threads; i++) { - delete _threads[i]; - } - FREE_C_HEAP_ARRAY(G1ConcurrentRefineThread*, _threads); } void G1ConcurrentRefine::threads_do(ThreadClosure *tc) { - for (uint i = 0; i < _n_worker_threads; i++) { - tc->do_thread(_threads[i]); - } + _thread_control.worker_threads_do(tc); } -uint G1ConcurrentRefine::thread_num() { +uint G1ConcurrentRefine::max_num_threads() { return G1ConcRefinementThreads; } void G1ConcurrentRefine::print_threads_on(outputStream* st) const { - for (uint i = 0; i < _n_worker_threads; ++i) { - _threads[i]->print_on(st); - st->cr(); - } + _thread_control.print_on(st); } static size_t calc_new_green_zone(size_t green, @@ -326,16 +381,15 @@ void G1ConcurrentRefine::adjust(double update_rs_time, if (G1UseAdaptiveConcRefinement) { update_zones(update_rs_time, update_rs_processed_buffers, goal_ms); - update_thread_thresholds(); // Change the barrier params - if (_n_worker_threads == 0) { + if (max_num_threads() == 0) { // Disable dcqs notification when there are no threads to notify. dcqs.set_process_completed_threshold(INT_MAX); } else { // Worker 0 is the primary; wakeup is via dcqs notification. STATIC_ASSERT(max_yellow_zone <= INT_MAX); - size_t activate = _threads[0]->activation_threshold(); + size_t activate = activation_threshold(0); dcqs.set_process_completed_threshold((int)activate); } dcqs.set_max_completed_queue((int)red_zone()); @@ -349,3 +403,42 @@ void G1ConcurrentRefine::adjust(double update_rs_time, } dcqs.notify_if_necessary(); } + +size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const { + Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id); + return activation_level(thresholds); +} + +size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const { + Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id); + return deactivation_level(thresholds); +} + +uint G1ConcurrentRefine::worker_id_offset() { + return DirtyCardQueueSet::num_par_ids(); +} + +void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) { + if (num_cur_buffers > activation_threshold(worker_id + 1)) { + _thread_control.maybe_activate_next(worker_id); + } +} + +bool G1ConcurrentRefine::do_refinement_step(uint worker_id) { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + + size_t curr_buffer_num = dcqs.completed_buffers_num(); + // If the number of the buffers falls down into the yellow zone, + // that means that the transition period after the evacuation pause has ended. + // Since the value written to the DCQS is the same for all threads, there is no + // need to synchronize. + if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= yellow_zone()) { + dcqs.set_completed_queue_padding(0); + } + + maybe_activate_more_threads(worker_id, curr_buffer_num); + + // Process the next buffer, if there are enough left. + return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(), + deactivation_threshold(worker_id)); +} diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp index b64d4e3ee80..52783881b9e 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp @@ -30,30 +30,63 @@ // Forward decl class CardTableEntryClosure; +class G1ConcurrentRefine; class G1ConcurrentRefineThread; class outputStream; class ThreadClosure; -class G1ConcurrentRefine : public CHeapObj { +// Helper class for refinement thread management. Used to start, stop and +// iterate over them. +class G1ConcurrentRefineThreadControl VALUE_OBJ_CLASS_SPEC { + G1ConcurrentRefine* _cr; + G1ConcurrentRefineThread** _threads; - uint _n_worker_threads; - /* - * The value of the update buffer queue length falls into one of 3 zones: - * green, yellow, red. If the value is in [0, green) nothing is - * done, the buffers are left unprocessed to enable the caching effect of the - * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement - * threads are gradually activated. In [yellow, red) all threads are - * running. If the length becomes red (max queue length) the mutators start - * processing the buffers. - * - * There are some interesting cases (when G1UseAdaptiveConcRefinement - * is turned off): - * 1) green = yellow = red = 0. In this case the mutator will process all - * buffers. Except for those that are created by the deferred updates - * machinery during a collection. - * 2) green = 0. Means no caching. Can be a good way to minimize the - * amount of time spent updating rsets during a collection. - */ + uint _num_max_threads; + + // Create the refinement thread for the given worker id. + // If initializing is true, ignore InjectGCWorkerCreationFailure. + G1ConcurrentRefineThread* create_refinement_thread(uint worker_id, bool initializing); +public: + G1ConcurrentRefineThreadControl(); + ~G1ConcurrentRefineThreadControl(); + + jint initialize(G1ConcurrentRefine* cr, uint num_max_threads); + + // If there is a "successor" thread that can be activated given the current id, + // activate it. + void maybe_activate_next(uint cur_worker_id); + + void print_on(outputStream* st) const; + void worker_threads_do(ThreadClosure* tc); + void stop(); +}; + +// Controls refinement threads and their activation based on the number of completed +// buffers currently available in the global dirty card queue. +// Refinement threads pick work from the queue based on these thresholds. They are activated +// gradually based on the amount of work to do. +// Refinement thread n activates thread n+1 if the instance of this class determines there +// is enough work available. Threads deactivate themselves if the current amount of +// completed buffers falls below their individual threshold. +class G1ConcurrentRefine : public CHeapObj { + G1ConcurrentRefineThreadControl _thread_control; + /* + * The value of the completed dirty card queue length falls into one of 3 zones: + * green, yellow, red. If the value is in [0, green) nothing is + * done, the buffers are left unprocessed to enable the caching effect of the + * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement + * threads are gradually activated. In [yellow, red) all threads are + * running. If the length becomes red (max queue length) the mutators start + * processing the buffers. + * + * There are some interesting cases (when G1UseAdaptiveConcRefinement + * is turned off): + * 1) green = yellow = red = 0. In this case the mutator will process all + * buffers. Except for those that are created by the deferred updates + * machinery during a collection. + * 2) green = 0. Means no caching. Can be a good way to minimize the + * amount of time spent updating remembered sets during a collection. + */ size_t _green_zone; size_t _yellow_zone; size_t _red_zone; @@ -69,24 +102,32 @@ class G1ConcurrentRefine : public CHeapObj { size_t update_rs_processed_buffers, double goal_ms); - // Update thread thresholds to account for updated zone values. - void update_thread_thresholds(); + static uint worker_id_offset(); + void maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers); - public: + jint initialize(); +public: ~G1ConcurrentRefine(); - // Returns a G1ConcurrentRefine instance if succeeded to create/initialize G1ConcurrentRefine and G1ConcurrentRefineThreads. - // Otherwise, returns NULL with error code. + // Returns a G1ConcurrentRefine instance if succeeded to create/initialize the + // G1ConcurrentRefine instance. Otherwise, returns NULL with error code. static G1ConcurrentRefine* create(jint* ecode); void stop(); + // Adjust refinement thresholds based on work done during the pause and the goal time. void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms); + size_t activation_threshold(uint worker_id) const; + size_t deactivation_threshold(uint worker_id) const; + // Perform a single refinement step. Called by the refinement threads when woken up. + bool do_refinement_step(uint worker_id); + // Iterate over all concurrent refinement threads applying the given closure. void threads_do(ThreadClosure *tc); - static uint thread_num(); + // Maximum number of refinement threads. + static uint max_num_threads(); void print_threads_on(outputStream* st) const; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp index f62e0c369e8..e1d1f8f4d01 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp @@ -25,32 +25,20 @@ #include "precompiled.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1RemSet.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" -G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, - G1ConcurrentRefineThread *next, - uint worker_id_offset, - uint worker_id, - size_t activate, - size_t deactivate) : +G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) : ConcurrentGCThread(), - _worker_id_offset(worker_id_offset), _worker_id(worker_id), _active(false), - _next(next), _monitor(NULL), _cr(cr), - _vtime_accum(0.0), - _activation_threshold(activate), - _deactivation_threshold(deactivate) + _vtime_accum(0.0) { - // Each thread has its own monitor. The i-th thread is responsible for signaling // to thread i+1 if the number of buffers in the queue exceeds a threshold for this // thread. Monitors are also used to wake up the threads during termination. @@ -67,13 +55,6 @@ G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, create_and_start(); } -void G1ConcurrentRefineThread::update_thresholds(size_t activate, - size_t deactivate) { - assert(deactivate < activate, "precondition"); - _activation_threshold = activate; - _deactivation_threshold = deactivate; -} - void G1ConcurrentRefineThread::wait_for_completed_buffers() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); while (!should_terminate() && !is_active()) { @@ -118,9 +99,9 @@ void G1ConcurrentRefineThread::run_service() { } size_t buffers_processed = 0; - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); - log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, - _worker_id, _activation_threshold, dcqs.completed_buffers_num()); + log_debug(gc, refine)("Activated worker %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, + _worker_id, _cr->activation_threshold(_worker_id), + JavaThread::dirty_card_queue_set().completed_buffers_num()); { SuspendibleThreadSetJoiner sts_join; @@ -131,33 +112,18 @@ void G1ConcurrentRefineThread::run_service() { continue; // Re-check for termination after yield delay. } - size_t curr_buffer_num = dcqs.completed_buffers_num(); - // If the number of the buffers falls down into the yellow zone, - // that means that the transition period after the evacuation pause has ended. - if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cr()->yellow_zone()) { - dcqs.set_completed_queue_padding(0); - } - - // Check if we need to activate the next thread. - if ((_next != NULL) && - !_next->is_active() && - (curr_buffer_num > _next->_activation_threshold)) { - _next->activate(); - } - - // Process the next buffer, if there are enough left. - if (!dcqs.refine_completed_buffer_concurrently(_worker_id + _worker_id_offset, _deactivation_threshold)) { - break; // Deactivate, number of buffers fell below threshold. + if (!_cr->do_refinement_step(_worker_id)) { + break; } ++buffers_processed; } } deactivate(); - log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT + log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT, - _worker_id, _deactivation_threshold, - dcqs.completed_buffers_num(), + _worker_id, _cr->deactivation_threshold(_worker_id), + JavaThread::dirty_card_queue_set().completed_buffers_num(), buffers_processed); if (os::supports_vtime()) { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp index fbc10fcfb4c..8b3694411fa 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp @@ -43,43 +43,29 @@ class G1ConcurrentRefineThread: public ConcurrentGCThread { uint _worker_id; uint _worker_id_offset; - // The refinement threads collection is linked list. A predecessor can activate a successor - // when the number of the rset update buffer crosses a certain threshold. A successor - // would self-deactivate when the number of the buffers falls below the threshold. bool _active; - G1ConcurrentRefineThread* _next; Monitor* _monitor; G1ConcurrentRefine* _cr; - // This thread's activation/deactivation thresholds - size_t _activation_threshold; - size_t _deactivation_threshold; - void wait_for_completed_buffers(); void set_active(bool x) { _active = x; } - bool is_active(); - void activate(); + // Deactivate this thread. void deactivate(); bool is_primary() { return (_worker_id == 0); } void run_service(); void stop_service(); - public: - // Constructor - G1ConcurrentRefineThread(G1ConcurrentRefine* cr, G1ConcurrentRefineThread* next, - uint worker_id_offset, uint worker_id, - size_t activate, size_t deactivate); + G1ConcurrentRefineThread(G1ConcurrentRefine* cg1r, uint worker_id); - void update_thresholds(size_t activate, size_t deactivate); - size_t activation_threshold() const { return _activation_threshold; } + bool is_active(); + // Activate this thread. + void activate(); // Total virtual time so far. double vtime_accum() { return _vtime_accum; } - - G1ConcurrentRefine* cr() { return _cr; } }; #endif // SHARE_VM_GC_G1_G1CONCURRENTREFINETHREAD_HPP diff --git a/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp b/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp index 409c8ba99aa..4c480ca5827 100644 --- a/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp +++ b/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp @@ -52,7 +52,7 @@ G1DefaultPolicy::G1DefaultPolicy(STWGCTimer* gc_timer) : _analytics(new G1Analytics(&_predictor)), _mmu_tracker(new G1MMUTrackerQueue(GCPauseIntervalMillis / 1000.0, MaxGCPauseMillis / 1000.0)), _ihop_control(create_ihop_control(&_predictor)), - _policy_counters(new GCPolicyCounters("GarbageFirst", 1, 3)), + _policy_counters(new GCPolicyCounters("GarbageFirst", 1, 2)), _young_list_fixed_length(0), _short_lived_surv_rate_group(new SurvRateGroup()), _survivor_surv_rate_group(new SurvRateGroup()), diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index 81ec9a05e25..ffe54d28332 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -35,6 +35,7 @@ #include "gc/g1/g1FullGCReferenceProcessorExecutor.hpp" #include "gc/g1/g1FullGCScope.hpp" #include "gc/g1/g1OopClosures.hpp" +#include "gc/g1/g1Policy.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/preservedMarks.hpp" @@ -62,20 +63,24 @@ static void update_derived_pointers() { #endif } -G1FullCollector::G1FullCollector(G1FullGCScope* scope, - ReferenceProcessor* reference_processor, - G1CMBitMap* bitmap, - uint workers) : - _scope(scope), - _num_workers(workers), - _mark_bitmap(bitmap), +G1CMBitMap* G1FullCollector::mark_bitmap() { + return _heap->concurrent_mark()->next_mark_bitmap(); +} + +ReferenceProcessor* G1FullCollector::reference_processor() { + return _heap->ref_processor_stw(); +} + +G1FullCollector::G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs) : + _heap(heap), + _scope(memory_manager, explicit_gc, clear_soft_refs), + _num_workers(heap->workers()->active_workers()), _oop_queue_set(_num_workers), _array_queue_set(_num_workers), _preserved_marks_set(true), - _reference_processor(reference_processor), _serial_compaction_point(), - _is_alive(_mark_bitmap), - _is_alive_mutator(_reference_processor, &_is_alive) { + _is_alive(heap->concurrent_mark()->next_mark_bitmap()), + _is_alive_mutator(heap->ref_processor_stw(), &_is_alive) { assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); _preserved_marks_set.init(_num_workers); @@ -99,8 +104,19 @@ G1FullCollector::~G1FullCollector() { } void G1FullCollector::prepare_collection() { - _reference_processor->enable_discovery(); - _reference_processor->setup_policy(scope()->should_clear_soft_refs()); + _heap->g1_policy()->record_full_collection_start(); + + _heap->print_heap_before_gc(); + _heap->print_heap_regions(); + + _heap->abort_concurrent_cycle(); + _heap->verify_before_full_collection(scope()->is_explicit_gc()); + + _heap->gc_prologue(true); + _heap->prepare_heap_for_full_collection(); + + reference_processor()->enable_discovery(); + reference_processor()->setup_policy(scope()->should_clear_soft_refs()); // When collecting the permanent generation Method*s may be moving, // so we either have to flush all bcp data or convert it into bci. @@ -139,6 +155,15 @@ void G1FullCollector::complete_collection() { BiasedLocking::restore_marks(); CodeCache::gc_epilogue(); JvmtiExport::gc_epilogue(); + + _heap->prepare_heap_for_mutators(); + + _heap->g1_policy()->record_full_collection_end(); + _heap->gc_epilogue(true); + + _heap->verify_after_full_collection(); + + _heap->print_heap_after_full_collection(scope()->heap_transition()); } void G1FullCollector::phase1_mark_live_objects() { @@ -164,11 +189,11 @@ void G1FullCollector::phase1_mark_live_objects() { GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer()); // Unload classes and purge the SystemDictionary. bool purged_class = SystemDictionary::do_unloading(&_is_alive, scope()->timer()); - G1CollectedHeap::heap()->complete_cleaning(&_is_alive, purged_class); + _heap->complete_cleaning(&_is_alive, purged_class); } else { GCTraceTime(Debug, gc, phases) debug("Phase 1: String and Symbol Tables Cleanup", scope()->timer()); // If no class unloading just clean out strings and symbols. - G1CollectedHeap::heap()->partial_cleaning(&_is_alive, true, true, G1StringDedup::is_enabled()); + _heap->partial_cleaning(&_is_alive, true, true, G1StringDedup::is_enabled()); } scope()->tracer()->report_object_count_after_gc(&_is_alive); @@ -210,18 +235,18 @@ void G1FullCollector::phase4_do_compaction() { } void G1FullCollector::restore_marks() { - SharedRestorePreservedMarksTaskExecutor task_executor(G1CollectedHeap::heap()->workers()); + SharedRestorePreservedMarksTaskExecutor task_executor(_heap->workers()); _preserved_marks_set.restore(&task_executor); _preserved_marks_set.reclaim(); } void G1FullCollector::run_task(AbstractGangTask* task) { - G1CollectedHeap::heap()->workers()->run_task(task, _num_workers); + _heap->workers()->run_task(task, _num_workers); } void G1FullCollector::verify_after_marking() { - if (!VerifyDuringGC) { - //Only do verification if VerifyDuringGC is set. + if (!VerifyDuringGC || !_heap->verifier()->should_verify(G1HeapVerifier::G1VerifyFull)) { + // Only do verification if VerifyDuringGC and G1VerifyFull is set. return; } @@ -229,7 +254,7 @@ void G1FullCollector::verify_after_marking() { #if COMPILER2_OR_JVMCI DerivedPointerTableDeactivate dpt_deact; #endif - G1CollectedHeap::heap()->prepare_for_verify(); + _heap->prepare_for_verify(); // Note: we can verify only the heap here. When an object is // marked, the previous value of the mark word (including // identity hash values, ages, etc) is preserved, and the mark @@ -240,6 +265,6 @@ void G1FullCollector::verify_after_marking() { // fail. At the end of the GC, the original mark word values // (including hash values) are restored to the appropriate // objects. - GCTraceTime(Info, gc, verify)("During GC (full)"); - G1CollectedHeap::heap()->verify(VerifyOption_G1UseFullMarking); + GCTraceTime(Info, gc, verify)("Verifying During GC (full)"); + _heap->verify(VerifyOption_G1UseFullMarking); } diff --git a/src/hotspot/share/gc/g1/g1FullCollector.hpp b/src/hotspot/share/gc/g1/g1FullCollector.hpp index 947304596ee..576aba5c8c6 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.hpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.hpp @@ -28,6 +28,7 @@ #include "gc/g1/g1FullGCCompactionPoint.hpp" #include "gc/g1/g1FullGCMarker.hpp" #include "gc/g1/g1FullGCOopClosures.hpp" +#include "gc/g1/g1FullGCScope.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/taskqueue.hpp" @@ -38,45 +39,41 @@ class G1CMBitMap; class G1FullGCMarker; class G1FullGCScope; class G1FullGCCompactionPoint; +class GCMemoryManager; class ReferenceProcessor; // The G1FullCollector holds data associated with the current Full GC. class G1FullCollector : StackObj { - G1FullGCScope* _scope; + G1CollectedHeap* _heap; + G1FullGCScope _scope; uint _num_workers; G1FullGCMarker** _markers; G1FullGCCompactionPoint** _compaction_points; - G1CMBitMap* _mark_bitmap; OopQueueSet _oop_queue_set; ObjArrayTaskQueueSet _array_queue_set; PreservedMarksSet _preserved_marks_set; - ReferenceProcessor* _reference_processor; G1FullGCCompactionPoint _serial_compaction_point; - G1IsAliveClosure _is_alive; ReferenceProcessorIsAliveMutator _is_alive_mutator; public: - G1FullCollector(G1FullGCScope* scope, - ReferenceProcessor* reference_processor, - G1CMBitMap* mark_bitmap, - uint workers); + G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs); ~G1FullCollector(); void prepare_collection(); void collect(); void complete_collection(); - G1FullGCScope* scope() { return _scope; } + G1FullGCScope* scope() { return &_scope; } uint workers() { return _num_workers; } G1FullGCMarker* marker(uint id) { return _markers[id]; } G1FullGCCompactionPoint* compaction_point(uint id) { return _compaction_points[id]; } - G1CMBitMap* mark_bitmap() { return _mark_bitmap; } OopQueueSet* oop_queue_set() { return &_oop_queue_set; } ObjArrayTaskQueueSet* array_queue_set() { return &_array_queue_set; } PreservedMarksSet* preserved_mark_set() { return &_preserved_marks_set; } - ReferenceProcessor* reference_processor() { return _reference_processor; } G1FullGCCompactionPoint* serial_compaction_point() { return &_serial_compaction_point; } + G1CMBitMap* mark_bitmap(); + ReferenceProcessor* reference_processor(); private: void phase1_mark_live_objects(); diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp index 95f01be62c6..0ec0b324aab 100644 --- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_G1_G1FULLGCCOMPACTIONPOINT_HPP #include "memory/allocation.hpp" +#include "oops/oopsHierarchy.hpp" #include "utilities/growableArray.hpp" class HeapRegion; diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.cpp b/src/hotspot/share/gc/g1/g1FullGCScope.cpp index 87dd42b93f3..2430451df1c 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.cpp @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "gc/g1/g1FullGCScope.hpp" -G1FullGCScope::G1FullGCScope(bool explicit_gc, bool clear_soft) : +G1FullGCScope::G1FullGCScope(GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft) : _rm(), _explicit_gc(explicit_gc), _g1h(G1CollectedHeap::heap()), @@ -36,7 +36,7 @@ G1FullGCScope::G1FullGCScope(bool explicit_gc, bool clear_soft) : _active(), _cpu_time(), _soft_refs(clear_soft, _g1h->collector_policy()), - _memory_stats(true, _g1h->gc_cause()), + _memory_stats(memory_manager, _g1h->gc_cause()), _collector_stats(_g1h->g1mm()->full_collection_counters()), _heap_transition(_g1h) { _timer.register_gc_start(); diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.hpp b/src/hotspot/share/gc/g1/g1FullGCScope.hpp index 20dc8d21643..850ee0aea0f 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.hpp @@ -37,6 +37,8 @@ #include "memory/allocation.hpp" #include "services/memoryService.hpp" +class GCMemoryManager; + // Class used to group scoped objects used in the Full GC together. class G1FullGCScope : public StackObj { ResourceMark _rm; @@ -54,7 +56,7 @@ class G1FullGCScope : public StackObj { G1HeapTransition _heap_transition; public: - G1FullGCScope(bool explicit_gc, bool clear_soft); + G1FullGCScope(GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft); ~G1FullGCScope(); bool is_explicit_gc(); diff --git a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp index 70e5ed29c65..ca1a22c78e0 100644 --- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp +++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp @@ -376,6 +376,37 @@ public: } }; +void G1HeapVerifier::parse_verification_type(const char* type) { + if (strcmp(type, "young-only") == 0) { + enable_verification_type(G1VerifyYoungOnly); + } else if (strcmp(type, "initial-mark") == 0) { + enable_verification_type(G1VerifyInitialMark); + } else if (strcmp(type, "mixed") == 0) { + enable_verification_type(G1VerifyMixed); + } else if (strcmp(type, "remark") == 0) { + enable_verification_type(G1VerifyRemark); + } else if (strcmp(type, "cleanup") == 0) { + enable_verification_type(G1VerifyCleanup); + } else if (strcmp(type, "full") == 0) { + enable_verification_type(G1VerifyFull); + } else { + log_warning(gc, verify)("VerifyGCType: '%s' is unknown. Available types are: " + "young-only, initial-mark, mixed, remark, cleanup and full", type); + } +} + +void G1HeapVerifier::enable_verification_type(G1VerifyType type) { + // First enable will clear _enabled_verification_types. + if (_enabled_verification_types == G1VerifyAll) { + _enabled_verification_types = type; + } else { + _enabled_verification_types |= type; + } +} + +bool G1HeapVerifier::should_verify(G1VerifyType type) { + return (_enabled_verification_types & type) == type; +} void G1HeapVerifier::verify(VerifyOption vo) { if (!SafepointSynchronize::is_at_safepoint()) { @@ -541,28 +572,32 @@ void G1HeapVerifier::prepare_for_verify() { } } -double G1HeapVerifier::verify(bool guard, const char* msg) { +double G1HeapVerifier::verify(G1VerifyType type, VerifyOption vo, const char* msg) { double verify_time_ms = 0.0; - if (guard && _g1h->total_collections() >= VerifyGCStartAt) { + if (should_verify(type) && _g1h->total_collections() >= VerifyGCStartAt) { double verify_start = os::elapsedTime(); HandleMark hm; // Discard invalid handles created during verification prepare_for_verify(); - Universe::verify(VerifyOption_G1UsePrevMarking, msg); + Universe::verify(vo, msg); verify_time_ms = (os::elapsedTime() - verify_start) * 1000; } return verify_time_ms; } -void G1HeapVerifier::verify_before_gc() { - double verify_time_ms = verify(VerifyBeforeGC, "Before GC"); - _g1h->g1_policy()->phase_times()->record_verify_before_time_ms(verify_time_ms); +void G1HeapVerifier::verify_before_gc(G1VerifyType type) { + if (VerifyBeforeGC) { + double verify_time_ms = verify(type, VerifyOption_G1UsePrevMarking, "Before GC"); + _g1h->g1_policy()->phase_times()->record_verify_before_time_ms(verify_time_ms); + } } -void G1HeapVerifier::verify_after_gc() { - double verify_time_ms = verify(VerifyAfterGC, "After GC"); - _g1h->g1_policy()->phase_times()->record_verify_after_time_ms(verify_time_ms); +void G1HeapVerifier::verify_after_gc(G1VerifyType type) { + if (VerifyAfterGC) { + double verify_time_ms = verify(type, VerifyOption_G1UsePrevMarking, "After GC"); + _g1h->g1_policy()->phase_times()->record_verify_after_time_ms(verify_time_ms); + } } diff --git a/src/hotspot/share/gc/g1/g1HeapVerifier.hpp b/src/hotspot/share/gc/g1/g1HeapVerifier.hpp index 6d3bb3899f8..ee7cb0a316b 100644 --- a/src/hotspot/share/gc/g1/g1HeapVerifier.hpp +++ b/src/hotspot/share/gc/g1/g1HeapVerifier.hpp @@ -34,6 +34,7 @@ class G1CollectedHeap; class G1HeapVerifier : public CHeapObj { private: G1CollectedHeap* _g1h; + int _enabled_verification_types; // verify_region_sets() performs verification over the region // lists. It will be compiled in the product code to be used when @@ -41,8 +42,21 @@ private: void verify_region_sets(); public: + enum G1VerifyType { + G1VerifyYoungOnly = 1, // -XX:VerifyGCType=young-only + G1VerifyInitialMark = 2, // -XX:VerifyGCType=initial-mark + G1VerifyMixed = 4, // -XX:VerifyGCType=mixed + G1VerifyRemark = 8, // -XX:VerifyGCType=remark + G1VerifyCleanup = 16, // -XX:VerifyGCType=cleanup + G1VerifyFull = 32, // -XX:VerifyGCType=full + G1VerifyAll = -1 + }; - G1HeapVerifier(G1CollectedHeap* heap) : _g1h(heap) { } + G1HeapVerifier(G1CollectedHeap* heap) : _g1h(heap), _enabled_verification_types(G1VerifyAll) { } + + void parse_verification_type(const char* type); + void enable_verification_type(G1VerifyType type); + bool should_verify(G1VerifyType type); // Perform verification. @@ -73,9 +87,9 @@ public: #endif // HEAP_REGION_SET_FORCE_VERIFY void prepare_for_verify(); - double verify(bool guard, const char* msg); - void verify_before_gc(); - void verify_after_gc(); + double verify(G1VerifyType type, VerifyOption vo, const char* msg); + void verify_before_gc(G1VerifyType type); + void verify_after_gc(G1VerifyType type); #ifndef PRODUCT // Make sure that the given bitmap has no marked objects in the diff --git a/src/hotspot/share/services/g1MemoryPool.cpp b/src/hotspot/share/gc/g1/g1MemoryPool.cpp similarity index 95% rename from src/hotspot/share/services/g1MemoryPool.cpp rename to src/hotspot/share/gc/g1/g1MemoryPool.cpp index 92daa7b726d..f658c0d2a27 100644 --- a/src/hotspot/share/services/g1MemoryPool.cpp +++ b/src/hotspot/share/gc/g1/g1MemoryPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, 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 @@ -24,8 +24,8 @@ #include "precompiled.hpp" #include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1MemoryPool.hpp" #include "gc/g1/heapRegion.hpp" -#include "services/g1MemoryPool.hpp" G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h, const char* name, @@ -33,7 +33,6 @@ G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h, size_t max_size, bool support_usage_threshold) : _g1mm(g1h->g1mm()), CollectedMemoryPool(name, - MemoryPool::Heap, init_size, max_size, support_usage_threshold) { diff --git a/src/hotspot/share/services/g1MemoryPool.hpp b/src/hotspot/share/gc/g1/g1MemoryPool.hpp similarity index 92% rename from src/hotspot/share/services/g1MemoryPool.hpp rename to src/hotspot/share/gc/g1/g1MemoryPool.hpp index fddc439e899..a6771c3fd79 100644 --- a/src/hotspot/share/services/g1MemoryPool.hpp +++ b/src/hotspot/share/gc/g1/g1MemoryPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, 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,15 +22,12 @@ * */ -#ifndef SHARE_VM_SERVICES_G1MEMORYPOOL_HPP -#define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP +#ifndef SHARE_VM_GC_G1_G1MEMORYPOOL_HPP +#define SHARE_VM_GC_G1_G1MEMORYPOOL_HPP -#include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS #include "gc/g1/g1MonitoringSupport.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif // INCLUDE_ALL_GCS // This file contains the three classes that represent the memory // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and @@ -50,6 +47,8 @@ // on this model. // +class G1CollectedHeap; + // This class is shared by the three G1 memory pool classes // (G1EdenPool, G1SurvivorPool, G1OldGenPool). class G1MemoryPoolSuper : public CollectedMemoryPool { @@ -107,4 +106,4 @@ public: MemoryUsage get_memory_usage(); }; -#endif // SHARE_VM_SERVICES_G1MEMORYPOOL_HPP +#endif // SHARE_VM_GC_G1_G1MEMORYPOOL_HPP diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp index a0cf7c2c3cf..0a566b3afc0 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp @@ -26,6 +26,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1Policy.hpp" +#include "gc/shared/hSpaceCounters.hpp" G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm, const char* name, @@ -128,10 +129,10 @@ G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : // name "generation.1.space.0" // Counters are created from maxCapacity, capacity, initCapacity, // and used. - _old_space_counters = new HSpaceCounters("space", 0 /* ordinal */, + _old_space_counters = new HSpaceCounters(_old_collection_counters->name_space(), + "space", 0 /* ordinal */, pad_capacity(overall_reserved()) /* max_capacity */, - pad_capacity(old_space_committed()) /* init_capacity */, - _old_collection_counters); + pad_capacity(old_space_committed()) /* init_capacity */); // Young collection set // name "generation.0". This is logically the young generation. @@ -139,27 +140,29 @@ G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : // See _old_collection_counters for additional counters _young_collection_counters = new G1YoungGenerationCounters(this, "young"); + const char* young_collection_name_space = _young_collection_counters->name_space(); + // name "generation.0.space.0" // See _old_space_counters for additional counters - _eden_counters = new HSpaceCounters("eden", 0 /* ordinal */, + _eden_counters = new HSpaceCounters(young_collection_name_space, + "eden", 0 /* ordinal */, pad_capacity(overall_reserved()) /* max_capacity */, - pad_capacity(eden_space_committed()) /* init_capacity */, - _young_collection_counters); + pad_capacity(eden_space_committed()) /* init_capacity */); // name "generation.0.space.1" // See _old_space_counters for additional counters // Set the arguments to indicate that this survivor space is not used. - _from_counters = new HSpaceCounters("s0", 1 /* ordinal */, + _from_counters = new HSpaceCounters(young_collection_name_space, + "s0", 1 /* ordinal */, pad_capacity(0) /* max_capacity */, - pad_capacity(0) /* init_capacity */, - _young_collection_counters); + pad_capacity(0) /* init_capacity */); // name "generation.0.space.2" // See _old_space_counters for additional counters - _to_counters = new HSpaceCounters("s1", 2 /* ordinal */, + _to_counters = new HSpaceCounters(young_collection_name_space, + "s1", 2 /* ordinal */, pad_capacity(overall_reserved()) /* max_capacity */, - pad_capacity(survivor_space_committed()) /* init_capacity */, - _young_collection_counters); + pad_capacity(survivor_space_committed()) /* init_capacity */); if (UsePerfData) { // Given that this survivor space is not used, we update it here diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp index 3c1d7444108..ee103237009 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp @@ -25,9 +25,11 @@ #ifndef SHARE_VM_GC_G1_G1MONITORINGSUPPORT_HPP #define SHARE_VM_GC_G1_G1MONITORINGSUPPORT_HPP -#include "gc/g1/hSpaceCounters.hpp" +#include "gc/shared/generationCounters.hpp" +class CollectorCounters; class G1CollectedHeap; +class HSpaceCounters; // Class for monitoring logical spaces in G1. It provides data for // both G1's jstat counters as well as G1's memory pools. diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index 32b405d4226..03e75f1989d 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -32,6 +32,7 @@ #include "gc/g1/g1StringDedup.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/taskqueue.inline.hpp" +#include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/prefetch.inline.hpp" @@ -390,3 +391,21 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) { } } +G1ParScanThreadStateSet::G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers, size_t young_cset_length) : + _g1h(g1h), + _states(NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC)), + _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)), + _young_cset_length(young_cset_length), + _n_workers(n_workers), + _flushed(false) { + for (uint i = 0; i < n_workers; ++i) { + _states[i] = NULL; + } + memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t)); +} + +G1ParScanThreadStateSet::~G1ParScanThreadStateSet() { + assert(_flushed, "thread local state from the per thread states should have been flushed"); + FREE_C_HEAP_ARRAY(G1ParScanThreadState*, _states); + FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_total); +} diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 9bbb9a90a62..310b4270b02 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -204,24 +204,8 @@ class G1ParScanThreadStateSet : public StackObj { bool _flushed; public: - G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers, size_t young_cset_length) : - _g1h(g1h), - _states(NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC)), - _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)), - _young_cset_length(young_cset_length), - _n_workers(n_workers), - _flushed(false) { - for (uint i = 0; i < n_workers; ++i) { - _states[i] = NULL; - } - memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t)); - } - - ~G1ParScanThreadStateSet() { - assert(_flushed, "thread local state from the per thread states should have been flushed"); - FREE_C_HEAP_ARRAY(G1ParScanThreadState*, _states); - FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_total); - } + G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers, size_t young_cset_length); + ~G1ParScanThreadStateSet(); void flush(); diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index da0281c6130..c20a41e66f0 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -298,7 +298,7 @@ G1RemSet::~G1RemSet() { } uint G1RemSet::num_par_rem_sets() { - return MAX2(DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::thread_num(), ParallelGCThreads); + return MAX2(DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads(), ParallelGCThreads); } void G1RemSet::initialize(size_t capacity, uint max_regions) { diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index 2ddabe75d03..93a8f713836 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -86,7 +86,7 @@ G1RemSetSummary::G1RemSetSummary() : _num_processed_buf_mutator(0), _num_processed_buf_rs_threads(0), _num_coarsenings(0), - _num_vtimes(G1ConcurrentRefine::thread_num()), + _num_vtimes(G1ConcurrentRefine::max_num_threads()), _rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)), _sampling_thread_vtime(0.0f) { @@ -99,7 +99,7 @@ G1RemSetSummary::G1RemSetSummary(G1RemSet* rem_set) : _num_processed_buf_mutator(0), _num_processed_buf_rs_threads(0), _num_coarsenings(0), - _num_vtimes(G1ConcurrentRefine::thread_num()), + _num_vtimes(G1ConcurrentRefine::max_num_threads()), _rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)), _sampling_thread_vtime(0.0f) { update(); diff --git a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp index 9db03fdfc5f..5c1bc491e5d 100644 --- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp +++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp @@ -175,6 +175,9 @@ void G1SATBCardTableLoggingModRefBS::write_ref_field_post_slow(volatile jbyte* b void G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr) { + if (mr.is_empty()) { + return; + } volatile jbyte* byte = byte_for(mr.start()); jbyte* last_byte = byte_for(mr.last()); Thread* thr = Thread::current(); diff --git a/src/hotspot/share/gc/g1/satbMarkQueue.cpp b/src/hotspot/share/gc/g1/satbMarkQueue.cpp index ddca44b038c..178cb450c9b 100644 --- a/src/hotspot/share/gc/g1/satbMarkQueue.cpp +++ b/src/hotspot/share/gc/g1/satbMarkQueue.cpp @@ -32,6 +32,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vmThread.hpp" SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) : @@ -214,7 +215,7 @@ void SATBMarkQueueSet::dump_active_states(bool expected_active) { log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE"); log_error(gc, verify)("Actual SATB active states:"); log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE"); - for (JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { log_error(gc, verify)(" Thread \"%s\" queue: %s", t->name(), t->satb_mark_queue().is_active() ? "ACTIVE" : "INACTIVE"); } log_error(gc, verify)(" Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE"); @@ -228,7 +229,7 @@ void SATBMarkQueueSet::verify_active_states(bool expected_active) { } // Verify thread queue states - for (JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { if (t->satb_mark_queue().is_active() != expected_active) { dump_active_states(expected_active); guarantee(false, "Thread SATB queue has an unexpected active state"); @@ -249,14 +250,14 @@ void SATBMarkQueueSet::set_active_all_threads(bool active, bool expected_active) verify_active_states(expected_active); #endif // ASSERT _all_active = active; - for (JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { t->satb_mark_queue().set_active(active); } shared_satb_queue()->set_active(active); } void SATBMarkQueueSet::filter_thread_buffers() { - for(JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { t->satb_mark_queue().filter(); } shared_satb_queue()->filter(); @@ -309,7 +310,7 @@ void SATBMarkQueueSet::print_all(const char* msg) { i += 1; } - for (JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name()); t->satb_mark_queue().print(buffer); } @@ -341,8 +342,8 @@ void SATBMarkQueueSet::abandon_partial_marking() { } assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); // So we can safely manipulate these queues. - for (JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { t->satb_mark_queue().reset(); } - shared_satb_queue()->reset(); + shared_satb_queue()->reset(); } diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 120ff95bae5..7d5fd87d5c1 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -29,6 +29,7 @@ #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "utilities/align.hpp" MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment), _must_use_large_pages(false) { @@ -90,14 +91,14 @@ void MutableNUMASpace::ensure_parsability() { MutableSpace *s = ls->space(); if (s->top() < top()) { // For all spaces preceding the one containing top() if (s->free_in_words() > 0) { - intptr_t cur_top = (intptr_t)s->top(); + HeapWord* cur_top = s->top(); size_t words_left_to_fill = pointer_delta(s->end(), s->top());; while (words_left_to_fill > 0) { size_t words_to_fill = MIN2(words_left_to_fill, CollectedHeap::filler_array_max_size()); assert(words_to_fill >= CollectedHeap::min_fill_size(), "Remaining size (" SIZE_FORMAT ") is too small to fill (based on " SIZE_FORMAT " and " SIZE_FORMAT ")", words_to_fill, words_left_to_fill, CollectedHeap::filler_array_max_size()); - CollectedHeap::fill_with_object((HeapWord*)cur_top, words_to_fill); + CollectedHeap::fill_with_object(cur_top, words_to_fill); if (!os::numa_has_static_binding()) { size_t touched_words = words_to_fill; #ifndef ASSERT @@ -107,19 +108,19 @@ void MutableNUMASpace::ensure_parsability() { } #endif MemRegion invalid; - HeapWord *crossing_start = align_up((HeapWord*)cur_top, os::vm_page_size()); - HeapWord *crossing_end = align_down((HeapWord*)(cur_top + touched_words), os::vm_page_size()); + HeapWord *crossing_start = align_up(cur_top, os::vm_page_size()); + HeapWord *crossing_end = align_down(cur_top + touched_words, os::vm_page_size()); if (crossing_start != crossing_end) { // If object header crossed a small page boundary we mark the area // as invalid rounding it to a page_size(). - HeapWord *start = MAX2(align_down((HeapWord*)cur_top, page_size()), s->bottom()); - HeapWord *end = MIN2(align_up((HeapWord*)(cur_top + touched_words), page_size()), s->end()); + HeapWord *start = MAX2(align_down(cur_top, page_size()), s->bottom()); + HeapWord *end = MIN2(align_up(cur_top + touched_words, page_size()), s->end()); invalid = MemRegion(start, end); } ls->add_invalid_region(invalid); } - cur_top = cur_top + (words_to_fill * HeapWordSize); + cur_top += words_to_fill; words_left_to_fill -= words_to_fill; } } @@ -287,7 +288,7 @@ bool MutableNUMASpace::update_layout(bool force) { FREE_C_HEAP_ARRAY(int, lgrp_ids); if (changed) { - for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { thread->set_lgrp_id(-1); } } diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 27fcf5c1adc..4fc4bc76e3b 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -33,6 +33,7 @@ #include "gc/parallel/parallelScavengeHeap.inline.hpp" #include "gc/parallel/psAdaptiveSizePolicy.hpp" #include "gc/parallel/psMarkSweep.hpp" +#include "gc/parallel/psMemoryPool.hpp" #include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/psPromotionManager.hpp" #include "gc/parallel/psScavenge.hpp" @@ -45,6 +46,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/vmThread.hpp" +#include "services/memoryManager.hpp" #include "services/memTracker.hpp" #include "utilities/vmError.hpp" @@ -105,9 +107,9 @@ jint ParallelScavengeHeap::initialize() { (old_gen()->virtual_space()->high_boundary() == young_gen()->virtual_space()->low_boundary()), "Boundaries must meet"); - // initialize the policy counters - 2 collectors, 3 generations + // initialize the policy counters - 2 collectors, 2 generations _gc_policy_counters = - new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 3, _size_policy); + new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 2, _size_policy); // Set up the GCTaskManager _gc_task_manager = GCTaskManager::create(ParallelGCThreads); @@ -119,7 +121,35 @@ jint ParallelScavengeHeap::initialize() { return JNI_OK; } +void ParallelScavengeHeap::initialize_serviceability() { + + _eden_pool = new EdenMutableSpacePool(_young_gen, + _young_gen->eden_space(), + "PS Eden Space", + false /* support_usage_threshold */); + + _survivor_pool = new SurvivorMutableSpacePool(_young_gen, + "PS Survivor Space", + false /* support_usage_threshold */); + + _old_pool = new PSGenerationPool(_old_gen, + "PS Old Gen", + true /* support_usage_threshold */); + + _young_manager = new GCMemoryManager("PS Scavenge", "end of minor GC"); + _old_manager = new GCMemoryManager("PS MarkSweep", "end of major GC"); + + _old_manager->add_pool(_eden_pool); + _old_manager->add_pool(_survivor_pool); + _old_manager->add_pool(_old_pool); + + _young_manager->add_pool(_eden_pool); + _young_manager->add_pool(_survivor_pool); + +} + void ParallelScavengeHeap::post_initialize() { + CollectedHeap::post_initialize(); // Need to init the tenuring threshold PSScavenge::initialize(); if (UseParallelOldGC) { @@ -674,3 +704,19 @@ void ParallelScavengeHeap::register_nmethod(nmethod* nm) { void ParallelScavengeHeap::verify_nmethod(nmethod* nm) { CodeCache::verify_scavenge_root_nmethod(nm); } + +GrowableArray ParallelScavengeHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(_young_manager); + memory_managers.append(_old_manager); + return memory_managers; +} + +GrowableArray ParallelScavengeHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} + diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index bfdc55f07f7..2eca2b12dcd 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,11 +36,14 @@ #include "gc/shared/gcWhen.hpp" #include "gc/shared/strongRootsScope.hpp" #include "memory/metaspace.hpp" +#include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" class AdjoiningGenerations; class GCHeapSummary; class GCTaskManager; +class MemoryManager; +class MemoryPool; class PSAdaptiveSizePolicy; class PSHeapSummary; @@ -64,6 +67,15 @@ class ParallelScavengeHeap : public CollectedHeap { // The task manager static GCTaskManager* _gc_task_manager; + GCMemoryManager* _young_manager; + GCMemoryManager* _old_manager; + + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; + + virtual void initialize_serviceability(); + void trace_heap(GCWhen::Type when, const GCTracer* tracer); protected: @@ -94,6 +106,9 @@ class ParallelScavengeHeap : public CollectedHeap { virtual CollectorPolicy* collector_policy() const { return _collector_policy; } + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + static PSYoungGen* young_gen() { return _young_gen; } static PSOldGen* old_gen() { return _old_gen; } @@ -244,6 +259,9 @@ class ParallelScavengeHeap : public CollectedHeap { ParStrongRootsScope(); ~ParStrongRootsScope(); }; + + GCMemoryManager* old_gc_manager() const { return _old_manager; } + GCMemoryManager* young_gc_manager() const { return _young_manager; } }; // Simple class for storing info about the heap at the start of GC, to be used diff --git a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp index d4350f7db6c..437356866df 100644 --- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp +++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp @@ -29,6 +29,7 @@ #include "gc/parallel/psScavenge.hpp" #include "gc/shared/collectorPolicy.hpp" #include "gc/shared/gcCause.hpp" +#include "gc/shared/gcUtil.inline.hpp" #include "gc/shared/gcPolicyCounters.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" diff --git a/src/hotspot/share/gc/parallel/psGenerationCounters.cpp b/src/hotspot/share/gc/parallel/psGenerationCounters.cpp index d200258acdf..1b0e8d320a9 100644 --- a/src/hotspot/share/gc/parallel/psGenerationCounters.cpp +++ b/src/hotspot/share/gc/parallel/psGenerationCounters.cpp @@ -25,9 +25,9 @@ #include "precompiled.hpp" #include "gc/parallel/psGenerationCounters.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" - PSGenerationCounters::PSGenerationCounters(const char* name, int ordinal, int spaces, size_t min_capacity, diff --git a/src/hotspot/share/gc/parallel/psMarkSweep.cpp b/src/hotspot/share/gc/parallel/psMarkSweep.cpp index 185cbb2f62d..2ac25afc016 100644 --- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp +++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp @@ -172,7 +172,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { heap->pre_full_gc_dump(_gc_timer); TraceCollectorStats tcs(counters()); - TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); + TraceMemoryManagerStats tms(heap->old_gc_manager(),gc_cause); if (log_is_enabled(Debug, gc, heap, exit)) { accumulated_time()->start(); diff --git a/src/hotspot/share/services/psMemoryPool.cpp b/src/hotspot/share/gc/parallel/psMemoryPool.cpp similarity index 81% rename from src/hotspot/share/services/psMemoryPool.cpp rename to src/hotspot/share/gc/parallel/psMemoryPool.cpp index 8e356cea27b..92e94efdfa2 100644 --- a/src/hotspot/share/services/psMemoryPool.cpp +++ b/src/hotspot/share/gc/parallel/psMemoryPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, 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,21 +23,12 @@ */ #include "precompiled.hpp" -#include "classfile/systemDictionary.hpp" -#include "classfile/vmSymbols.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/handles.inline.hpp" -#include "runtime/javaCalls.hpp" -#include "services/lowMemoryDetector.hpp" -#include "services/management.hpp" -#include "services/memoryManager.hpp" -#include "services/psMemoryPool.hpp" +#include "gc/parallel/psMemoryPool.hpp" PSGenerationPool::PSGenerationPool(PSOldGen* old_gen, const char* name, - PoolType type, bool support_usage_threshold) : - CollectedMemoryPool(name, type, old_gen->capacity_in_bytes(), + CollectedMemoryPool(name, old_gen->capacity_in_bytes(), old_gen->reserved().byte_size(), support_usage_threshold), _old_gen(old_gen) { } @@ -58,9 +49,8 @@ MemoryUsage PSGenerationPool::get_memory_usage() { EdenMutableSpacePool::EdenMutableSpacePool(PSYoungGen* young_gen, MutableSpace* space, const char* name, - PoolType type, bool support_usage_threshold) : - CollectedMemoryPool(name, type, space->capacity_in_bytes(), + CollectedMemoryPool(name, space->capacity_in_bytes(), (young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes()), support_usage_threshold), _young_gen(young_gen), @@ -82,9 +72,8 @@ MemoryUsage EdenMutableSpacePool::get_memory_usage() { // SurvivorMutableSpacePool::SurvivorMutableSpacePool(PSYoungGen* young_gen, const char* name, - PoolType type, bool support_usage_threshold) : - CollectedMemoryPool(name, type, young_gen->from_space()->capacity_in_bytes(), + CollectedMemoryPool(name, young_gen->from_space()->capacity_in_bytes(), young_gen->from_space()->capacity_in_bytes(), support_usage_threshold), _young_gen(young_gen) { } diff --git a/src/hotspot/share/services/psMemoryPool.hpp b/src/hotspot/share/gc/parallel/psMemoryPool.hpp similarity index 82% rename from src/hotspot/share/services/psMemoryPool.hpp rename to src/hotspot/share/gc/parallel/psMemoryPool.hpp index f1a900caa0f..522799d8336 100644 --- a/src/hotspot/share/services/psMemoryPool.hpp +++ b/src/hotspot/share/gc/parallel/psMemoryPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, 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,28 +25,22 @@ #ifndef SHARE_VM_SERVICES_PSMEMORYPOOL_HPP #define SHARE_VM_SERVICES_PSMEMORYPOOL_HPP -#include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS #include "gc/parallel/mutableSpace.hpp" #include "gc/parallel/psOldGen.hpp" #include "gc/parallel/psYoungGen.hpp" -#include "gc/serial/defNewGeneration.hpp" -#include "gc/shared/space.hpp" -#include "memory/heap.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif // INCLUDE_ALL_GCS class PSGenerationPool : public CollectedMemoryPool { private: PSOldGen* _old_gen; public: - PSGenerationPool(PSOldGen* pool, const char* name, PoolType type, bool support_usage_threshold); + PSGenerationPool(PSOldGen* pool, const char* name, bool support_usage_threshold); MemoryUsage get_memory_usage(); - size_t used_in_bytes() { return _old_gen->used_in_bytes(); } - size_t max_size() const { return _old_gen->reserved().byte_size(); } + size_t used_in_bytes() { return _old_gen->used_in_bytes(); } + size_t max_size() const { return _old_gen->reserved().byte_size(); } }; class EdenMutableSpacePool : public CollectedMemoryPool { @@ -58,7 +52,6 @@ public: EdenMutableSpacePool(PSYoungGen* young_gen, MutableSpace* space, const char* name, - PoolType type, bool support_usage_threshold); MutableSpace* space() { return _space; } @@ -77,7 +70,6 @@ private: public: SurvivorMutableSpacePool(PSYoungGen* young_gen, const char* name, - PoolType type, bool support_usage_threshold); MemoryUsage get_memory_usage(); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index c46f0d41aa0..be23ea77681 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1772,7 +1772,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { heap->pre_full_gc_dump(&_gc_timer); TraceCollectorStats tcs(counters()); - TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); + TraceMemoryManagerStats tms(heap->old_gc_manager(), gc_cause); if (log_is_enabled(Debug, gc, heap, exit)) { accumulated_time()->start(); diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 64c0b7486ab..5bcb21bf9ff 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -305,7 +305,7 @@ bool PSScavenge::invoke_no_policy() { GCTraceCPUTime tcpu; GCTraceTime(Info, gc) tm("Pause Young", NULL, gc_cause, true); TraceCollectorStats tcs(counters()); - TraceMemoryManagerStats tms(false /* not full GC */,gc_cause); + TraceMemoryManagerStats tms(heap->young_gc_manager(), gc_cause); if (log_is_enabled(Debug, gc, heap, exit)) { accumulated_time()->start(); diff --git a/src/hotspot/share/gc/parallel/spaceCounters.cpp b/src/hotspot/share/gc/parallel/spaceCounters.cpp index 36cb8099523..3a7231d8b25 100644 --- a/src/hotspot/share/gc/parallel/spaceCounters.cpp +++ b/src/hotspot/share/gc/parallel/spaceCounters.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/parallel/spaceCounters.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "utilities/macros.hpp" @@ -63,3 +64,7 @@ SpaceCounters::SpaceCounters(const char* name, int ordinal, size_t max_size, _object_space->capacity_in_bytes(), CHECK); } } + +SpaceCounters::~SpaceCounters() { + if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); +} diff --git a/src/hotspot/share/gc/parallel/spaceCounters.hpp b/src/hotspot/share/gc/parallel/spaceCounters.hpp index 38e6542085f..e2cf1621b3d 100644 --- a/src/hotspot/share/gc/parallel/spaceCounters.hpp +++ b/src/hotspot/share/gc/parallel/spaceCounters.hpp @@ -53,9 +53,7 @@ class SpaceCounters: public CHeapObj { SpaceCounters(const char* name, int ordinal, size_t max_size, MutableSpace* m, GenerationCounters* gc); - ~SpaceCounters() { - if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); - } + ~SpaceCounters(); inline void update_capacity() { _capacity->set_value(_object_space->capacity_in_bytes()); diff --git a/src/hotspot/share/gc/serial/cSpaceCounters.cpp b/src/hotspot/share/gc/serial/cSpaceCounters.cpp index 84e9c96bd4e..076902d1dca 100644 --- a/src/hotspot/share/gc/serial/cSpaceCounters.cpp +++ b/src/hotspot/share/gc/serial/cSpaceCounters.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/serial/cSpaceCounters.hpp" +#include "memory/allocation.inline.hpp" #include "memory/metaspace.hpp" #include "memory/resourceArea.hpp" @@ -64,6 +65,10 @@ CSpaceCounters::CSpaceCounters(const char* name, int ordinal, size_t max_size, } } +CSpaceCounters::~CSpaceCounters() { + if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); +} + void CSpaceCounters::update_capacity() { _capacity->set_value(_space->capacity()); } diff --git a/src/hotspot/share/gc/serial/cSpaceCounters.hpp b/src/hotspot/share/gc/serial/cSpaceCounters.hpp index ffe43ab14a2..da0c4cfbf31 100644 --- a/src/hotspot/share/gc/serial/cSpaceCounters.hpp +++ b/src/hotspot/share/gc/serial/cSpaceCounters.hpp @@ -52,9 +52,7 @@ class CSpaceCounters: public CHeapObj { CSpaceCounters(const char* name, int ordinal, size_t max_size, ContiguousSpace* s, GenerationCounters* gc); - ~CSpaceCounters() { - if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); - } + ~CSpaceCounters(); virtual void update_capacity(); virtual void update_used(); diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index c4c17a8a386..c395e11fd27 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -23,9 +23,44 @@ */ #include "precompiled.hpp" +#include "gc/serial/defNewGeneration.hpp" #include "gc/serial/serialHeap.hpp" +#include "gc/shared/genMemoryPools.hpp" +#include "services/memoryManager.hpp" -SerialHeap::SerialHeap(GenCollectorPolicy* policy) : GenCollectedHeap(policy) {} +SerialHeap::SerialHeap(GenCollectorPolicy* policy) : + GenCollectedHeap(policy), _eden_pool(NULL), _survivor_pool(NULL), _old_pool(NULL) { + _young_manager = new GCMemoryManager("Copy", "end of minor GC"); + _old_manager = new GCMemoryManager("MarkSweepCompact", "end of major GC"); +} + +void SerialHeap::initialize_serviceability() { + + DefNewGeneration* young = (DefNewGeneration*) young_gen(); + + // Add a memory pool for each space and young gen doesn't + // support low memory detection as it is expected to get filled up. + _eden_pool = new ContiguousSpacePool(young->eden(), + "Eden Space", + young->max_eden_size(), + false /* support_usage_threshold */); + _survivor_pool = new SurvivorContiguousSpacePool(young, + "Survivor Space", + young->max_survivor_size(), + false /* support_usage_threshold */); + Generation* old = old_gen(); + _old_pool = new GenerationPool(old, "Tenured Gen", true); + + _young_manager->add_pool(_eden_pool); + _young_manager->add_pool(_survivor_pool); + young->set_gc_manager(_young_manager); + + _old_manager->add_pool(_eden_pool); + _old_manager->add_pool(_survivor_pool); + _old_manager->add_pool(_old_pool); + old->set_gc_manager(_old_manager); + +} void SerialHeap::check_gen_kinds() { assert(young_gen()->kind() == Generation::DefNew, @@ -33,3 +68,18 @@ void SerialHeap::check_gen_kinds() { assert(old_gen()->kind() == Generation::MarkSweepCompact, "Wrong generation kind"); } + +GrowableArray SerialHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(_young_manager); + memory_managers.append(_old_manager); + return memory_managers; +} + +GrowableArray SerialHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 8b96006638a..8df86f2e4bf 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -26,10 +26,20 @@ #define SHARE_VM_GC_SERIAL_SERIALHEAP_HPP #include "gc/shared/genCollectedHeap.hpp" +#include "utilities/growableArray.hpp" class GenCollectorPolicy; +class GCMemoryManager; +class MemoryPool; class SerialHeap : public GenCollectedHeap { +private: + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; + + virtual void initialize_serviceability(); + protected: virtual void check_gen_kinds(); @@ -44,6 +54,9 @@ public: return "Serial"; } + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + // override virtual bool is_in_closed_subset(const void* p) const { return is_in(p); @@ -52,7 +65,6 @@ public: virtual bool card_mark_must_follow_store() const { return false; } - }; #endif // SHARE_VM_GC_CMS_CMSHEAP_HPP diff --git a/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp b/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp index 9aa3f79c08d..830835f19dc 100644 --- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp +++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp @@ -26,6 +26,7 @@ #include "gc/shared/adaptiveSizePolicy.hpp" #include "gc/shared/collectorPolicy.hpp" #include "gc/shared/gcCause.hpp" +#include "gc/shared/gcUtil.inline.hpp" #include "gc/shared/workgroup.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index b2a0dc53ceb..a32fd69a3fb 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -40,6 +40,7 @@ #include "oops/oop.inline.hpp" #include "runtime/init.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "services/heapDumper.hpp" #include "utilities/align.hpp" @@ -540,10 +541,11 @@ void CollectedHeap::ensure_parsability(bool retire_tlabs) { const bool deferred = _defer_initial_card_mark; // The main thread starts allocating via a TLAB even before it // has added itself to the threads list at vm boot-up. - assert(!use_tlab || Threads::first() != NULL, + JavaThreadIteratorWithHandle jtiwh; + assert(!use_tlab || jtiwh.length() > 0, "Attempt to fill tlabs before main thread has been added" " to threads list is doomed to failure!"); - for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) { + for (; JavaThread *thread = jtiwh.next(); ) { if (use_tlab) thread->tlab().make_parsable(retire_tlabs); #if COMPILER2_OR_JVMCI // The deferred store barriers must all have been flushed to the @@ -609,3 +611,7 @@ void CollectedHeap::initialize_reserved_region(HeapWord *start, HeapWord *end) { _reserved.set_start(start); _reserved.set_end(end); } + +void CollectedHeap::post_initialize() { + initialize_serviceability(); +} diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 197eaf9b438..7be834d815c 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -34,6 +34,7 @@ #include "utilities/debug.hpp" #include "utilities/events.hpp" #include "utilities/formatBuffer.hpp" +#include "utilities/growableArray.hpp" // A "CollectedHeap" is an implementation of a java heap for HotSpot. This // is an abstract class: there may be many different kinds of heaps. This @@ -46,6 +47,8 @@ class CollectorPolicy; class GCHeapSummary; class GCTimer; class GCTracer; +class GCMemoryManager; +class MemoryPool; class MetaspaceSummary; class Thread; class ThreadClosure; @@ -217,7 +220,7 @@ class CollectedHeap : public CHeapObj { // In many heaps, there will be a need to perform some initialization activities // after the Universe is fully formed, but before general heap allocation is allowed. // This is the correct place to place such initialization methods. - virtual void post_initialize() = 0; + virtual void post_initialize(); // Stop any onging concurrent work and prepare for exit. virtual void stop() {} @@ -485,6 +488,9 @@ class CollectedHeap : public CHeapObj { // Return the CollectorPolicy for the heap virtual CollectorPolicy* collector_policy() const = 0; + virtual GrowableArray memory_managers() = 0; + virtual GrowableArray memory_pools() = 0; + // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl) = 0; @@ -529,6 +535,9 @@ class CollectedHeap : public CHeapObj { // Generate any dumps preceding or following a full gc private: void full_gc_dump(GCTimer* timer, bool before); + + virtual void initialize_serviceability() = 0; + public: void pre_full_gc_dump(GCTimer* timer); void post_full_gc_dump(GCTimer* timer); diff --git a/src/hotspot/share/gc/shared/collectorCounters.cpp b/src/hotspot/share/gc/shared/collectorCounters.cpp index b204a02e272..2a2e60f99b3 100644 --- a/src/hotspot/share/gc/shared/collectorCounters.cpp +++ b/src/hotspot/share/gc/shared/collectorCounters.cpp @@ -24,7 +24,9 @@ #include "precompiled.hpp" #include "gc/shared/collectorCounters.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "runtime/os.hpp" CollectorCounters::CollectorCounters(const char* name, int ordinal) { @@ -59,3 +61,24 @@ CollectorCounters::CollectorCounters(const char* name, int ordinal) { CHECK); } } + +CollectorCounters::~CollectorCounters() { + if (_name_space != NULL) { + FREE_C_HEAP_ARRAY(char, _name_space); + } +} + +TraceCollectorStats::TraceCollectorStats(CollectorCounters* c) : + PerfTraceTimedEvent(c->time_counter(), c->invocation_counter()), + _c(c) { + + if (UsePerfData) { + _c->last_entry_counter()->set_value(os::elapsed_counter()); + } +} + +TraceCollectorStats::~TraceCollectorStats() { + if (UsePerfData) { + _c->last_exit_counter()->set_value(os::elapsed_counter()); + } +} diff --git a/src/hotspot/share/gc/shared/collectorCounters.hpp b/src/hotspot/share/gc/shared/collectorCounters.hpp index 554d749e0cc..e9b272f03a9 100644 --- a/src/hotspot/share/gc/shared/collectorCounters.hpp +++ b/src/hotspot/share/gc/shared/collectorCounters.hpp @@ -49,9 +49,7 @@ class CollectorCounters: public CHeapObj { CollectorCounters(const char* name, int ordinal); - ~CollectorCounters() { - if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); - } + ~CollectorCounters(); inline PerfCounter* invocation_counter() const { return _invocations; } @@ -70,18 +68,9 @@ class TraceCollectorStats: public PerfTraceTimedEvent { CollectorCounters* _c; public: - inline TraceCollectorStats(CollectorCounters* c) : - PerfTraceTimedEvent(c->time_counter(), c->invocation_counter()), - _c(c) { + TraceCollectorStats(CollectorCounters* c); - if (UsePerfData) { - _c->last_entry_counter()->set_value(os::elapsed_counter()); - } - } - - inline ~TraceCollectorStats() { - if (UsePerfData) _c->last_exit_counter()->set_value(os::elapsed_counter()); - } + ~TraceCollectorStats(); }; #endif // SHARE_VM_GC_SHARED_COLLECTORCOUNTERS_HPP diff --git a/src/hotspot/share/gc/shared/collectorPolicy.cpp b/src/hotspot/share/gc/shared/collectorPolicy.cpp index 2d21024a3c7..7542662ee76 100644 --- a/src/hotspot/share/gc/shared/collectorPolicy.cpp +++ b/src/hotspot/share/gc/shared/collectorPolicy.cpp @@ -911,7 +911,7 @@ void MarkSweepPolicy::initialize_generations() { } void MarkSweepPolicy::initialize_gc_policy_counters() { - // Initialize the policy counters - 2 collectors, 3 generations. - _gc_policy_counters = new GCPolicyCounters("Copy:MSC", 2, 3); + // Initialize the policy counters - 2 collectors, 2 generations. + _gc_policy_counters = new GCPolicyCounters("Copy:MSC", 2, 2); } diff --git a/src/hotspot/share/gc/shared/gcArguments.cpp b/src/hotspot/share/gc/shared/gcArguments.cpp index 90432c5f48b..8162faf0c67 100644 --- a/src/hotspot/share/gc/shared/gcArguments.cpp +++ b/src/hotspot/share/gc/shared/gcArguments.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc/shared/gcArguments.hpp" #include "gc/serial/serialArguments.hpp" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "runtime/arguments.hpp" #include "runtime/globals.hpp" @@ -84,6 +85,12 @@ void GCArguments::select_gc_ergonomically() { #endif // INCLUDE_ALL_GCS } +bool GCArguments::parse_verification_type(const char* type) { + log_warning(gc, verify)("VerifyGCType is not supported by this collector."); + // Return false to avoid multiple warnings. + return false; +} + void GCArguments::initialize_flags() { #if INCLUDE_ALL_GCS if (MinHeapFreeRatio == 100) { @@ -99,6 +106,24 @@ void GCArguments::initialize_flags() { #endif // INCLUDE_ALL_GCS } +void GCArguments::post_heap_initialize() { + if (strlen(VerifyGCType) > 0) { + const char delimiter[] = " ,\n"; + size_t length = strlen(VerifyGCType); + char* type_list = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal); + strncpy(type_list, VerifyGCType, length + 1); + char* token = strtok(type_list, delimiter); + while (token != NULL) { + bool success = parse_verification_type(token); + if (!success) { + break; + } + token = strtok(NULL, delimiter); + } + FREE_C_HEAP_ARRAY(char, type_list); + } +} + jint GCArguments::initialize() { assert(!is_initialized(), "GC arguments already initialized"); diff --git a/src/hotspot/share/gc/shared/gcArguments.hpp b/src/hotspot/share/gc/shared/gcArguments.hpp index b04c12d4a85..3a3f89be136 100644 --- a/src/hotspot/share/gc/shared/gcArguments.hpp +++ b/src/hotspot/share/gc/shared/gcArguments.hpp @@ -46,8 +46,16 @@ public: static bool is_initialized(); static GCArguments* arguments(); + void post_heap_initialize(); + virtual void initialize_flags(); + // Collector specific function to allow finer grained verification + // through VerifyGCType. If not overridden the default version will + // warn that the flag is not supported for the given collector. + // Returns true if parsing should continue, false otherwise. + virtual bool parse_verification_type(const char* type); + virtual size_t conservative_max_heap_alignment() = 0; virtual CollectedHeap* create_heap() = 0; diff --git a/src/hotspot/share/gc/shared/gcLocker.cpp b/src/hotspot/share/gc/shared/gcLocker.cpp index 4b72cd80bfd..644d91116ba 100644 --- a/src/hotspot/share/gc/shared/gcLocker.cpp +++ b/src/hotspot/share/gc/shared/gcLocker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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,6 +29,7 @@ #include "logging/log.hpp" #include "runtime/atomic.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" volatile jint GCLocker::_jni_lock_count = 0; volatile bool GCLocker::_needs_gc = false; @@ -45,14 +46,16 @@ void GCLocker::verify_critical_count() { assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree"); int count = 0; // Count the number of threads with critical operations in progress - for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) { + JavaThreadIteratorWithHandle jtiwh; + for (; JavaThread *thr = jtiwh.next(); ) { if (thr->in_critical()) { count++; } } if (_jni_lock_count != count) { log_error(gc, verify)("critical counts don't match: %d != %d", _jni_lock_count, count); - for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) { + jtiwh.rewind(); + for (; JavaThread *thr = jtiwh.next(); ) { if (thr->in_critical()) { log_error(gc, verify)(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical()); } diff --git a/src/hotspot/share/gc/shared/gcStats.cpp b/src/hotspot/share/gc/shared/gcStats.cpp index 3a050f73066..14e63ea108f 100644 --- a/src/hotspot/share/gc/shared/gcStats.cpp +++ b/src/hotspot/share/gc/shared/gcStats.cpp @@ -24,8 +24,7 @@ #include "precompiled.hpp" #include "gc/shared/gcStats.hpp" -#include "gc/shared/gcUtil.hpp" -#include "memory/allocation.inline.hpp" +#include "gc/shared/gcUtil.inline.hpp" GCStats::GCStats() { _avg_promoted = new AdaptivePaddedNoZeroDevAverage( diff --git a/src/hotspot/share/gc/shared/gcUtil.hpp b/src/hotspot/share/gc/shared/gcUtil.hpp index 6b2f929bb5d..1fafbb51a00 100644 --- a/src/hotspot/share/gc/shared/gcUtil.hpp +++ b/src/hotspot/share/gc/shared/gcUtil.hpp @@ -146,7 +146,7 @@ class AdaptivePaddedAverage : public AdaptiveWeightedAverage { // Placement support void* operator new(size_t ignored, void* p) throw() { return p; } // Allocator - void* operator new(size_t size) throw() { return CHeapObj::operator new(size); } + void* operator new(size_t size) throw(); // Accessor float padded_average() const { return _padded_avg; } diff --git a/src/hotspot/share/gc/shared/gcUtil.inline.hpp b/src/hotspot/share/gc/shared/gcUtil.inline.hpp new file mode 100644 index 00000000000..f03480becde --- /dev/null +++ b/src/hotspot/share/gc/shared/gcUtil.inline.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002, 2015, 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_VM_GC_SHARED_GCUTIL_INLINE_HPP +#define SHARE_VM_GC_SHARED_GCUTIL_INLINE_HPP + +#include "gc/shared/gcUtil.hpp" +#include "memory/allocation.inline.hpp" + +inline void* AdaptivePaddedAverage::operator new(size_t size) throw() { + return CHeapObj::operator new(size); +} + +#endif // SHARE_VM_GC_SHARED_GCUTIL_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 5b21eb6a294..ae67feca465 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -143,6 +143,7 @@ char* GenCollectedHeap::allocate(size_t alignment, } void GenCollectedHeap::post_initialize() { + CollectedHeap::post_initialize(); ref_processing_init(); check_gen_kinds(); DefNewGeneration* def_new_gen = (DefNewGeneration*)_young_gen; @@ -270,7 +271,7 @@ void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t siz FormatBuffer<> title("Collect gen: %s", gen->short_name()); GCTraceTime(Trace, gc, phases) t1(title); TraceCollectorStats tcs(gen->counters()); - TraceMemoryManagerStats tmms(gen->kind(),gc_cause()); + TraceMemoryManagerStats tmms(gen->gc_manager(), gc_cause()); gen->stat_record()->invocations++; gen->stat_record()->accumulated_time.start(); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index 5eb4f749d14..e0a91302b0e 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -112,6 +112,9 @@ protected: // (gen-specific) roots processing. SubTasksDone* _process_strong_tasks; + GCMemoryManager* _young_manager; + GCMemoryManager* _old_manager; + // Helper functions for allocation HeapWord* attempt_allocation(size_t size, bool is_tlab, diff --git a/src/hotspot/share/gc/shared/genMemoryPools.cpp b/src/hotspot/share/gc/shared/genMemoryPools.cpp new file mode 100644 index 00000000000..292f2197c32 --- /dev/null +++ b/src/hotspot/share/gc/shared/genMemoryPools.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017, 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 "gc/serial/defNewGeneration.hpp" +#include "gc/shared/generation.hpp" +#include "gc/shared/genMemoryPools.hpp" +#include "gc/shared/space.hpp" + +ContiguousSpacePool::ContiguousSpacePool(ContiguousSpace* space, + const char* name, + size_t max_size, + bool support_usage_threshold) : + CollectedMemoryPool(name, space->capacity(), max_size, + support_usage_threshold), _space(space) { +} + +size_t ContiguousSpacePool::used_in_bytes() { + return space()->used(); +} + +MemoryUsage ContiguousSpacePool::get_memory_usage() { + size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = _space->capacity(); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} + +SurvivorContiguousSpacePool::SurvivorContiguousSpacePool(DefNewGeneration* young_gen, + const char* name, + size_t max_size, + bool support_usage_threshold) : + CollectedMemoryPool(name, young_gen->from()->capacity(), max_size, + support_usage_threshold), _young_gen(young_gen) { +} + +size_t SurvivorContiguousSpacePool::used_in_bytes() { + return _young_gen->from()->used(); +} + +size_t SurvivorContiguousSpacePool::committed_in_bytes() { + return _young_gen->from()->capacity(); +} + +MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() { + size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = committed_in_bytes(); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} + +GenerationPool::GenerationPool(Generation* gen, + const char* name, + bool support_usage_threshold) : + CollectedMemoryPool(name, gen->capacity(), gen->max_capacity(), + support_usage_threshold), _gen(gen) { +} + +size_t GenerationPool::used_in_bytes() { + return _gen->used(); +} + +MemoryUsage GenerationPool::get_memory_usage() { + size_t used = used_in_bytes(); + size_t committed = _gen->capacity(); + size_t maxSize = (available_for_allocation() ? max_size() : 0); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} diff --git a/src/hotspot/share/gc/shared/genMemoryPools.hpp b/src/hotspot/share/gc/shared/genMemoryPools.hpp new file mode 100644 index 00000000000..93ee91bf959 --- /dev/null +++ b/src/hotspot/share/gc/shared/genMemoryPools.hpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 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_VM_GC_SHARED_GENMEMORYPOOLS_HPP +#define SHARE_VM_GC_SHARED_GENMEMORYPOOLS_HPP + +#include "services/memoryPool.hpp" + +class ContiguousSpace; +class DefNewGeneration; +class Generation; + +class ContiguousSpacePool : public CollectedMemoryPool { +private: + ContiguousSpace* _space; + +public: + ContiguousSpacePool(ContiguousSpace* space, + const char* name, + size_t max_size, + bool support_usage_threshold); + + ContiguousSpace* space() { return _space; } + MemoryUsage get_memory_usage(); + size_t used_in_bytes(); +}; + +class SurvivorContiguousSpacePool : public CollectedMemoryPool { +private: + DefNewGeneration* _young_gen; + +public: + SurvivorContiguousSpacePool(DefNewGeneration* young_gen, + const char* name, + size_t max_size, + bool support_usage_threshold); + + MemoryUsage get_memory_usage(); + + size_t used_in_bytes(); + size_t committed_in_bytes(); +}; + +class GenerationPool : public CollectedMemoryPool { +private: + Generation* _gen; +public: + GenerationPool(Generation* gen, const char* name, bool support_usage_threshold); + + MemoryUsage get_memory_usage(); + size_t used_in_bytes(); +}; + +#endif // SHARE_VM_GC_SHARED_GENMEMORYPOOLS_HPP diff --git a/src/hotspot/share/gc/shared/generation.cpp b/src/hotspot/share/gc/shared/generation.cpp index 68c92230729..fbdb2f45b3f 100644 --- a/src/hotspot/share/gc/shared/generation.cpp +++ b/src/hotspot/share/gc/shared/generation.cpp @@ -44,7 +44,8 @@ #include "utilities/events.hpp" Generation::Generation(ReservedSpace rs, size_t initial_size) : - _ref_processor(NULL) { + _ref_processor(NULL), + _gc_manager(NULL) { if (!_virtual_space.initialize(rs, initial_size)) { vm_exit_during_initialization("Could not reserve enough space for " "object heap"); diff --git a/src/hotspot/share/gc/shared/generation.hpp b/src/hotspot/share/gc/shared/generation.hpp index 00d17a22a33..ea8f8d8b8ee 100644 --- a/src/hotspot/share/gc/shared/generation.hpp +++ b/src/hotspot/share/gc/shared/generation.hpp @@ -58,6 +58,7 @@ // class DefNewGeneration; +class GCMemoryManager; class GenerationSpec; class CompactibleSpace; class ContiguousSpace; @@ -86,6 +87,8 @@ class Generation: public CHeapObj { MemRegion _prev_used_region; // for collectors that want to "remember" a value for // used region at some specific point during collection. + GCMemoryManager* _gc_manager; + protected: // Minimum and maximum addresses for memory reserved (not necessarily // committed) for generation. @@ -554,6 +557,16 @@ public: // Performance Counter support virtual void update_counters() = 0; virtual CollectorCounters* counters() { return _gc_counters; } + + GCMemoryManager* gc_manager() const { + assert(_gc_manager != NULL, "not initialized yet"); + return _gc_manager; + } + + void set_gc_manager(GCMemoryManager* gc_manager) { + _gc_manager = gc_manager; + } + }; #endif // SHARE_VM_GC_SHARED_GENERATION_HPP diff --git a/src/hotspot/share/gc/shared/generationCounters.cpp b/src/hotspot/share/gc/shared/generationCounters.cpp index 134d28765e0..1efa58c4790 100644 --- a/src/hotspot/share/gc/shared/generationCounters.cpp +++ b/src/hotspot/share/gc/shared/generationCounters.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/shared/generationCounters.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" void GenerationCounters::initialize(const char* name, int ordinal, int spaces, @@ -78,6 +79,12 @@ GenerationCounters::GenerationCounters(const char* name, initialize(name, ordinal, spaces, min_capacity, max_capacity, curr_capacity); } +GenerationCounters::~GenerationCounters() { + if (_name_space != NULL) { + FREE_C_HEAP_ARRAY(char, _name_space); + } +} + void GenerationCounters::update_all() { assert(_virtual_space != NULL, "otherwise, override this method"); _current_size->set_value(_virtual_space->committed_size()); diff --git a/src/hotspot/share/gc/shared/generationCounters.hpp b/src/hotspot/share/gc/shared/generationCounters.hpp index 2b53549d575..71c42bb318c 100644 --- a/src/hotspot/share/gc/shared/generationCounters.hpp +++ b/src/hotspot/share/gc/shared/generationCounters.hpp @@ -68,9 +68,7 @@ private: GenerationCounters(const char* name, int ordinal, int spaces, size_t min_capacity, size_t max_capacity, VirtualSpace* v); - ~GenerationCounters() { - if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); - } + ~GenerationCounters(); virtual void update_all(); diff --git a/src/hotspot/share/gc/g1/hSpaceCounters.cpp b/src/hotspot/share/gc/shared/hSpaceCounters.cpp similarity index 69% rename from src/hotspot/share/gc/g1/hSpaceCounters.cpp rename to src/hotspot/share/gc/shared/hSpaceCounters.cpp index 7a5afddfedf..351c5cd920f 100644 --- a/src/hotspot/share/gc/g1/hSpaceCounters.cpp +++ b/src/hotspot/share/gc/shared/hSpaceCounters.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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,22 +23,23 @@ */ #include "precompiled.hpp" -#include "gc/g1/hSpaceCounters.hpp" -#include "gc/shared/generation.hpp" +#include "gc/shared/hSpaceCounters.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "runtime/perfData.hpp" -HSpaceCounters::HSpaceCounters(const char* name, +HSpaceCounters::HSpaceCounters(const char* name_space, + const char* name, int ordinal, size_t max_size, - size_t initial_capacity, - GenerationCounters* gc) { + size_t initial_capacity) { if (UsePerfData) { EXCEPTION_MARK; ResourceMark rm; const char* cns = - PerfDataManager::name_space(gc->name_space(), "space", ordinal); + PerfDataManager::name_space(name_space, "space", ordinal); _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC); strcpy(_name_space, cns); @@ -64,3 +65,33 @@ HSpaceCounters::HSpaceCounters(const char* name, initial_capacity, CHECK); } } + +HSpaceCounters::~HSpaceCounters() { + if (_name_space != NULL) { + FREE_C_HEAP_ARRAY(char, _name_space); + } +} + +void HSpaceCounters::update_capacity(size_t v) { + _capacity->set_value(v); +} + +void HSpaceCounters::update_used(size_t v) { + _used->set_value(v); +} + +void HSpaceCounters::update_all(size_t capacity, size_t used) { + update_capacity(capacity); + update_used(used); +} + +debug_only( + // for security reasons, we do not allow arbitrary reads from + // the counters as they may live in shared memory. + jlong HSpaceCounters::used() { + return _used->get_value(); + } + jlong HSpaceCounters::capacity() { + return _used->get_value(); + } +) diff --git a/src/hotspot/share/gc/g1/hSpaceCounters.hpp b/src/hotspot/share/gc/shared/hSpaceCounters.hpp similarity index 60% rename from src/hotspot/share/gc/g1/hSpaceCounters.hpp rename to src/hotspot/share/gc/shared/hSpaceCounters.hpp index fd7ed263415..36873fd8f70 100644 --- a/src/hotspot/share/gc/g1/hSpaceCounters.hpp +++ b/src/hotspot/share/gc/shared/hSpaceCounters.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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,65 +22,47 @@ * */ -#ifndef SHARE_VM_GC_G1_HSPACECOUNTERS_HPP -#define SHARE_VM_GC_G1_HSPACECOUNTERS_HPP +#ifndef SHARE_VM_GC_SHARED_HSPACECOUNTERS_HPP +#define SHARE_VM_GC_SHARED_HSPACECOUNTERS_HPP -#include "gc/shared/generation.hpp" -#include "gc/shared/generationCounters.hpp" +#include "memory/allocation.hpp" #include "runtime/perfData.hpp" #include "utilities/macros.hpp" // A HSpaceCounter is a holder class for performance counters // that track a collections (logical spaces) in a heap; -class HeapSpaceUsedHelper; -class G1SpaceMonitoringSupport; - class HSpaceCounters: public CHeapObj { friend class VMStructs; private: - PerfVariable* _capacity; - PerfVariable* _used; + PerfVariable* _capacity; + PerfVariable* _used; // Constant PerfData types don't need to retain a reference. // However, it's a good idea to document them here. - char* _name_space; + char* _name_space; public: - HSpaceCounters(const char* name, int ordinal, size_t max_size, - size_t initial_capacity, GenerationCounters* gc); + HSpaceCounters(const char* name_space, const char* name, int ordinal, + size_t max_size, size_t initial_capacity); - ~HSpaceCounters() { - if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); - } + ~HSpaceCounters(); - inline void update_capacity(size_t v) { - _capacity->set_value(v); - } + void update_capacity(size_t v); + void update_used(size_t v); - inline void update_used(size_t v) { - _used->set_value(v); - } + void update_all(size_t capacity, size_t used); debug_only( // for security reasons, we do not allow arbitrary reads from // the counters as they may live in shared memory. - jlong used() { - return _used->get_value(); - } - jlong capacity() { - return _used->get_value(); - } + jlong used(); + jlong capacity(); ) - inline void update_all(size_t capacity, size_t used) { - update_capacity(capacity); - update_used(used); - } - const char* name_space() const { return _name_space; } }; -#endif // SHARE_VM_GC_G1_HSPACECOUNTERS_HPP +#endif // SHARE_VM_GC_SHARED_HSPACECOUNTERS_HPP diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index ef1e9688bd4..ca0e1a02a58 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -26,6 +26,8 @@ #define SHARE_VM_GC_SHARED_TASKQUEUE_HPP #include "memory/allocation.hpp" +#include "oops/oopsHierarchy.hpp" +#include "utilities/ostream.hpp" #include "utilities/stack.hpp" // Simple TaskQueue stats that are collected by default in debug builds. @@ -425,7 +427,7 @@ class ParallelTaskTerminator: public StackObj { private: uint _n_threads; TaskQueueSetSuper* _queue_set; - uint _offered_termination; + volatile uint _offered_termination; #ifdef TRACESPINNING static uint _total_yields; diff --git a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp index e8828abbe40..6634a0cc906 100644 --- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp +++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp @@ -30,6 +30,7 @@ #include "memory/universe.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "utilities/copy.hpp" // Thread-Local Edens support @@ -48,7 +49,7 @@ void ThreadLocalAllocBuffer::clear_before_allocation() { void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() { global_stats()->initialize(); - for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { thread->tlab().accumulate_statistics(); thread->tlab().initialize_statistics(); } @@ -130,7 +131,7 @@ void ThreadLocalAllocBuffer::make_parsable(bool retire, bool zap) { void ThreadLocalAllocBuffer::resize_all_tlabs() { if (ResizeTLAB) { - for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { thread->tlab().resize(); } } diff --git a/src/hotspot/share/gc/shared/workgroup.cpp b/src/hotspot/share/gc/shared/workgroup.cpp index 73b3a2a55ab..2538e701fc9 100644 --- a/src/hotspot/share/gc/shared/workgroup.cpp +++ b/src/hotspot/share/gc/shared/workgroup.cpp @@ -261,6 +261,10 @@ WorkGang::WorkGang(const char* name, _dispatcher(create_dispatcher()) { } +WorkGang::~WorkGang() { + delete _dispatcher; +} + AbstractGangWorker* WorkGang::allocate_worker(uint worker_id) { return new GangWorker(this, worker_id); } diff --git a/src/hotspot/share/gc/shared/workgroup.hpp b/src/hotspot/share/gc/shared/workgroup.hpp index 320652a993c..c1b50f3885d 100644 --- a/src/hotspot/share/gc/shared/workgroup.hpp +++ b/src/hotspot/share/gc/shared/workgroup.hpp @@ -122,6 +122,8 @@ class AbstractWorkGang : public CHeapObj { // Printing support. const char* _name; + ~AbstractWorkGang() {} + private: // Initialize only instance data. const bool _are_GC_task_threads; @@ -206,9 +208,6 @@ class WorkGang: public AbstractWorkGang { // To get access to the GangTaskDispatcher instance. friend class GangWorker; - // Never deleted. - ~WorkGang(); - GangTaskDispatcher* const _dispatcher; GangTaskDispatcher* dispatcher() const { return _dispatcher; @@ -220,6 +219,8 @@ public: bool are_GC_task_threads, bool are_ConcurrentGC_threads); + ~WorkGang(); + // Run a task using the current active number of workers, returns when the task is done. virtual void run_task(AbstractGangTask* task); // Run a task with the given number of workers, returns diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 134ea685c83..ab5e3542fa9 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -42,6 +42,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/threadSMR.hpp" #include "utilities/debug.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" @@ -598,12 +599,13 @@ JRT_ENTRY(jint, JVMCIRuntime::identity_hash_code(JavaThread* thread, oopDesc* ob JRT_END JRT_ENTRY(jboolean, JVMCIRuntime::thread_is_interrupted(JavaThread* thread, oopDesc* receiver, jboolean clear_interrupted)) - // Ensure that the C++ Thread and OSThread structures aren't freed before we operate. - // This locking requires thread_in_vm which is why this method cannot be JRT_LEAF. Handle receiverHandle(thread, receiver); - MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock); + // A nested ThreadsListHandle may require the Threads_lock which + // requires thread_in_vm which is why this method cannot be JRT_LEAF. + ThreadsListHandle tlh; + JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle()); - if (receiverThread == NULL) { + if (receiverThread == NULL || (EnableThreadSMRExtraValidityChecks && !tlh.includes(receiverThread))) { // The other thread may exit during this process, which is ok so return false. return JNI_FALSE; } else { diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 66a9d859ed0..0f4ffa27113 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -317,6 +317,7 @@ \ nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \ nonstatic_field(Thread, _allocated_bytes, jlong) \ + nonstatic_field(Thread, _polling_page, address) \ \ nonstatic_field(ThreadLocalAllocBuffer, _start, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \ diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index e53e7cb4774..1956f27a078 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -121,6 +121,7 @@ LOG_TAG(safepoint) \ LOG_TAG(scavenge) \ LOG_TAG(scrub) \ + LOG_TAG(smr) \ LOG_TAG(stacktrace) \ LOG_TAG(stackwalk) \ LOG_TAG(start) \ diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 5671e12c2eb..18de6beaef9 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -785,7 +785,10 @@ class SpaceManager : public CHeapObj { Mutex* const _lock; // Type of metadata allocated. - Metaspace::MetadataType _mdtype; + const Metaspace::MetadataType _mdtype; + + // Type of metaspace + const Metaspace::MetaspaceType _space_type; // List of chunks in use by this SpaceManager. Allocations // are done from the current chunk. The list is used for deallocating @@ -796,6 +799,10 @@ class SpaceManager : public CHeapObj { // Maximum number of small chunks to allocate to a SpaceManager static uint const _small_chunk_limit; + // Maximum number of specialize chunks to allocate for anonymous + // metadata space to a SpaceManager + static uint const _anon_metadata_specialize_chunk_limit; + // Sum of all space in allocated chunks size_t _allocated_blocks_words; @@ -846,6 +853,7 @@ class SpaceManager : public CHeapObj { public: SpaceManager(Metaspace::MetadataType mdtype, + Metaspace::MetaspaceType space_type, Mutex* lock); ~SpaceManager(); @@ -963,6 +971,7 @@ class SpaceManager : public CHeapObj { }; uint const SpaceManager::_small_chunk_limit = 4; +uint const SpaceManager::_anon_metadata_specialize_chunk_limit = 4; const char* SpaceManager::_expand_lock_name = "SpaceManager chunk allocation lock"; @@ -2400,6 +2409,20 @@ size_t SpaceManager::calc_chunk_size(size_t word_size) { // _small_chunk_limit small chunks can be allocated. // After that a medium chunk is preferred. size_t chunk_word_size; + + // Special case for anonymous metadata space. + // Anonymous metadata space is usually small, with majority within 1K - 2K range and + // rarely about 4K (64-bits JVM). + // Instead of jumping to SmallChunk after initial chunk exhausted, keeping allocation + // from SpecializeChunk up to _anon_metadata_specialize_chunk_limit (4) reduces space waste + // from 60+% to around 30%. + if (_space_type == Metaspace::AnonymousMetaspaceType && + _mdtype == Metaspace::NonClassType && + sum_count_in_chunks_in_use(SpecializedIndex) < _anon_metadata_specialize_chunk_limit && + word_size + Metachunk::overhead() <= SpecializedChunk) { + return SpecializedChunk; + } + if (chunks_in_use(MediumIndex) == NULL && sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { chunk_word_size = (size_t) small_chunk_size(); @@ -2504,8 +2527,10 @@ void SpaceManager::print_on(outputStream* st) const { } SpaceManager::SpaceManager(Metaspace::MetadataType mdtype, + Metaspace::MetaspaceType space_type, Mutex* lock) : _mdtype(mdtype), + _space_type(space_type), _allocated_blocks_words(0), _allocated_chunks_words(0), _allocated_chunks_count(0), @@ -3781,11 +3806,11 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) { verify_global_initialization(); // Allocate SpaceManager for metadata objects. - _vsm = new SpaceManager(NonClassType, lock); + _vsm = new SpaceManager(NonClassType, type, lock); if (using_class_space()) { // Allocate SpaceManager for classes. - _class_vsm = new SpaceManager(ClassType, lock); + _class_vsm = new SpaceManager(ClassType, type, lock); } MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); diff --git a/src/hotspot/share/memory/resourceArea.cpp b/src/hotspot/share/memory/resourceArea.cpp index 3995e6335db..aca27c0b56a 100644 --- a/src/hotspot/share/memory/resourceArea.cpp +++ b/src/hotspot/share/memory/resourceArea.cpp @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "memory/allocation.inline.hpp" -#include "memory/resourceArea.hpp" +#include "memory/resourceArea.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/thread.inline.hpp" #include "services/memTracker.hpp" diff --git a/src/hotspot/share/memory/resourceArea.hpp b/src/hotspot/share/memory/resourceArea.hpp index 5fc13ac9243..32d57fd6e61 100644 --- a/src/hotspot/share/memory/resourceArea.hpp +++ b/src/hotspot/share/memory/resourceArea.hpp @@ -57,18 +57,7 @@ public: debug_only(_nesting = 0;); } - char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { -#ifdef ASSERT - if (_nesting < 1 && !_warned++) - fatal("memory leak: allocating without ResourceMark"); - if (UseMallocOnly) { - // use malloc, but save pointer in res. area for later freeing - char** save = (char**)internal_malloc_4(sizeof(char*)); - return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC)); - } -#endif - return (char*)Amalloc(size, alloc_failmode); - } + char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); // Bias this resource area to specific memory type // (by default, ResourceArea is tagged as mtThread, per-thread general purpose storage) diff --git a/src/hotspot/share/memory/resourceArea.inline.hpp b/src/hotspot/share/memory/resourceArea.inline.hpp new file mode 100644 index 00000000000..895c0b71bbf --- /dev/null +++ b/src/hotspot/share/memory/resourceArea.inline.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997, 2017, 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_VM_MEMORY_RESOURCEAREA_INLINE_HPP +#define SHARE_VM_MEMORY_RESOURCEAREA_INLINE_HPP + +#include "memory/resourceArea.hpp" + +inline char* ResourceArea::allocate_bytes(size_t size, AllocFailType alloc_failmode) { +#ifdef ASSERT + if (_nesting < 1 && !_warned++) + fatal("memory leak: allocating without ResourceMark"); + if (UseMallocOnly) { + // use malloc, but save pointer in res. area for later freeing + char** save = (char**)internal_malloc_4(sizeof(char*)); + return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC)); + } +#endif + return (char*)Amalloc(size, alloc_failmode); +} + +#endif // SHARE_VM_MEMORY_RESOURCEAREA_INLINE_HPP diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 32da59f6053..0dbad080700 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -687,6 +687,10 @@ jint universe_init() { Metaspace::global_initialize(); + // Initialize performance counters for metaspaces + MetaspaceCounters::initialize_performance_counters(); + CompressedClassSpaceCounters::initialize_performance_counters(); + AOTLoader::universe_init(); // Checks 'AfterMemoryInit' constraints. @@ -764,6 +768,7 @@ jint Universe::initialize_heap() { } log_info(gc)("Using %s", _collectedHeap->name()); + GCArguments::arguments()->post_heap_initialize(); ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size()); #ifdef _LP64 @@ -852,7 +857,7 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { || use_large_pages, "Wrong alignment to use large pages"); // Now create the space. - ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages); + ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages, AllocateHeapAt); if (total_rs.is_reserved()) { assert((total_reserved == total_rs.size()) && ((uintptr_t)total_rs.base() % alignment == 0), @@ -866,6 +871,9 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { Universe::set_narrow_oop_base((address)total_rs.compressed_oop_base()); } + if (AllocateHeapAt != NULL) { + log_info(gc,heap)("Successfully allocated Java heap at location %s", AllocateHeapAt); + } return total_rs; } @@ -1085,10 +1093,6 @@ bool universe_post_init() { // ("weak") refs processing infrastructure initialization Universe::heap()->post_initialize(); - // Initialize performance counters for metaspaces - MetaspaceCounters::initialize_performance_counters(); - CompressedClassSpaceCounters::initialize_performance_counters(); - MemoryService::add_metaspace_memory_pools(); MemoryService::set_universe_heap(Universe::heap()); diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index a3289d9b043..759210aace1 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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,10 +35,10 @@ // Dummy constructor ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0), - _alignment(0), _special(false), _executable(false) { + _alignment(0), _special(false), _executable(false), _fd_for_heap(-1) { } -ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) { +ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) : _fd_for_heap(-1) { bool has_preferred_page_size = preferred_page_size != 0; // Want to use large pages where possible and pad with small pages. size_t page_size = has_preferred_page_size ? preferred_page_size : os::page_size_for_region_unaligned(size, 1); @@ -59,19 +59,30 @@ ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) { ReservedSpace::ReservedSpace(size_t size, size_t alignment, bool large, - char* requested_address) { + char* requested_address) : _fd_for_heap(-1) { initialize(size, alignment, large, requested_address, false); } ReservedSpace::ReservedSpace(size_t size, size_t alignment, bool large, - bool executable) { + bool executable) : _fd_for_heap(-1) { initialize(size, alignment, large, NULL, executable); } +// Helper method +static void unmap_or_release_memory(char* base, size_t size, bool is_file_mapped) { + if (is_file_mapped) { + if (!os::unmap_memory(base, size)) { + fatal("os::unmap_memory failed"); + } + } else if (!os::release_memory(base, size)) { + fatal("os::release_memory failed"); + } +} + // Helper method. static bool failed_to_reserve_as_requested(char* base, char* requested_address, - const size_t size, bool special) + const size_t size, bool special, bool is_file_mapped = false) { if (base == requested_address || requested_address == NULL) return false; // did not fail @@ -87,9 +98,7 @@ static bool failed_to_reserve_as_requested(char* base, char* requested_address, fatal("os::release_memory_special failed"); } } else { - if (!os::release_memory(base, size)) { - fatal("os::release_memory failed"); - } + unmap_or_release_memory(base, size, is_file_mapped); } } return true; @@ -120,7 +129,18 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // If OS doesn't support demand paging for large page memory, we need // to use reserve_memory_special() to reserve and pin the entire region. + // If there is a backing file directory for this space then whether + // large pages are allocated is up to the filesystem of the backing file. + // So we ignore the UseLargePages flag in this case. bool special = large && !os::can_commit_large_page_memory(); + if (special && _fd_for_heap != -1) { + special = false; + if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || + !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { + log_debug(gc, heap)("Ignoring UseLargePages since large page support is up to the file system of the backing file for Java heap"); + } + } + char* base = NULL; if (special) { @@ -157,13 +177,13 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // important. If available space is not detected, return NULL. if (requested_address != 0) { - base = os::attempt_reserve_memory_at(size, requested_address); - if (failed_to_reserve_as_requested(base, requested_address, size, false)) { + base = os::attempt_reserve_memory_at(size, requested_address, _fd_for_heap); + if (failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) { // OS ignored requested address. Try different address. base = NULL; } } else { - base = os::reserve_memory(size, NULL, alignment); + base = os::reserve_memory(size, NULL, alignment, _fd_for_heap); } if (base == NULL) return; @@ -171,13 +191,14 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // Check alignment constraints if ((((size_t)base) & (alignment - 1)) != 0) { // Base not aligned, retry - if (!os::release_memory(base, size)) fatal("os::release_memory failed"); + unmap_or_release_memory(base, size, _fd_for_heap != -1 /*is_file_mapped*/); + // Make sure that size is aligned size = align_up(size, alignment); - base = os::reserve_memory_aligned(size, alignment); + base = os::reserve_memory_aligned(size, alignment, _fd_for_heap); if (requested_address != 0 && - failed_to_reserve_as_requested(base, requested_address, size, false)) { + failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) { // As a result of the alignment constraints, the allocated base differs // from the requested address. Return back to the caller who can // take remedial action (like try again without a requested address). @@ -190,6 +211,10 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, _base = base; _size = size; _alignment = alignment; + // If heap is reserved with a backing file, the entire space has been committed. So set the _special flag to true + if (_fd_for_heap != -1) { + _special = true; + } } @@ -252,7 +277,11 @@ void ReservedSpace::release() { char *real_base = _base - _noaccess_prefix; const size_t real_size = _size + _noaccess_prefix; if (special()) { - os::release_memory_special(real_base, real_size); + if (_fd_for_heap != -1) { + os::unmap_memory(real_base, real_size); + } else { + os::release_memory_special(real_base, real_size); + } } else{ os::release_memory(real_base, real_size); } @@ -313,7 +342,17 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, // If OS doesn't support demand paging for large page memory, we need // to use reserve_memory_special() to reserve and pin the entire region. + // If there is a backing file directory for this space then whether + // large pages are allocated is up to the filesystem of the backing file. + // So we ignore the UseLargePages flag in this case. bool special = large && !os::can_commit_large_page_memory(); + if (special && _fd_for_heap != -1) { + special = false; + if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || + !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { + log_debug(gc, heap)("Cannot allocate large pages for Java Heap when AllocateHeapAt option is set."); + } + } char* base = NULL; log_trace(gc, heap, coops)("Trying to allocate at address " PTR_FORMAT @@ -350,9 +389,9 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, // important. If available space is not detected, return NULL. if (requested_address != 0) { - base = os::attempt_reserve_memory_at(size, requested_address); + base = os::attempt_reserve_memory_at(size, requested_address, _fd_for_heap); } else { - base = os::reserve_memory(size, NULL, alignment); + base = os::reserve_memory(size, NULL, alignment, _fd_for_heap); } } if (base == NULL) { return; } @@ -362,6 +401,11 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, _size = size; _alignment = alignment; + // If heap is reserved with a backing file, the entire space has been committed. So set the _special flag to true + if (_fd_for_heap != -1) { + _special = true; + } + // Check alignment constraints if ((((size_t)base) & (alignment - 1)) != 0) { // Base not aligned, retry. @@ -556,12 +600,20 @@ void ReservedHeapSpace::initialize_compressed_heap(const size_t size, size_t ali } } -ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, bool large) : ReservedSpace() { +ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, bool large, const char* heap_allocation_directory) : ReservedSpace() { if (size == 0) { return; } + if (heap_allocation_directory != NULL) { + _fd_for_heap = os::create_file_for_heap(heap_allocation_directory); + if (_fd_for_heap == -1) { + vm_exit_during_initialization( + err_msg("Could not create file for Heap at location %s", heap_allocation_directory)); + } + } + // Heap size should be aligned to alignment, too. guarantee(is_aligned(size, alignment), "set by caller"); @@ -585,6 +637,10 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, bool large) if (base() != NULL) { MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap); } + + if (_fd_for_heap != -1) { + os::close(_fd_for_heap); + } } // Reserve space for code segment. Same as Java heap only we mark this as diff --git a/src/hotspot/share/memory/virtualspace.hpp b/src/hotspot/share/memory/virtualspace.hpp index 2475f09d156..5041ce145ec 100644 --- a/src/hotspot/share/memory/virtualspace.hpp +++ b/src/hotspot/share/memory/virtualspace.hpp @@ -37,6 +37,7 @@ class ReservedSpace VALUE_OBJ_CLASS_SPEC { size_t _noaccess_prefix; size_t _alignment; bool _special; + int _fd_for_heap; private: bool _executable; @@ -115,7 +116,9 @@ class ReservedHeapSpace : public ReservedSpace { void establish_noaccess_prefix(); public: // Constructor. Tries to find a heap that is good for compressed oops. - ReservedHeapSpace(size_t size, size_t forced_base_alignment, bool large); + // heap_allocation_directory is the path to the backing memory for Java heap. When set, Java heap will be allocated + // on the device which is managed by the file system where the directory resides. + ReservedHeapSpace(size_t size, size_t forced_base_alignment, bool large, const char* heap_allocation_directory = NULL); // Returns the base to be used for compression, i.e. so that null can be // encoded safely and implicit null checks can work. char *compressed_oop_base() { return _base - _noaccess_prefix; } diff --git a/src/hotspot/share/oops/array.hpp b/src/hotspot/share/oops/array.hpp index 225331e0521..f56da8e26e0 100644 --- a/src/hotspot/share/oops/array.hpp +++ b/src/hotspot/share/oops/array.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_OOPS_ARRAY_HPP #include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" #include "memory/metaspace.hpp" #include "runtime/orderAccess.hpp" #include "utilities/align.hpp" diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 9e1eefd5251..4dd2e35e2cf 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -31,6 +31,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/allocation.inline.hpp" #include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" @@ -2300,3 +2301,11 @@ SymbolHashMapEntry* SymbolHashMap::find_entry(Symbol* sym) { } return NULL; } + +void SymbolHashMap::initialize_table(int table_size) { + _table_size = table_size; + _buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size, mtSymbol); + for (int index = 0; index < table_size; index++) { + _buckets[index].clear(); + } +} diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index 681935edae5..8dc75922419 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -982,13 +982,7 @@ class SymbolHashMap: public CHeapObj { int _table_size; SymbolHashMapBucket* _buckets; - void initialize_table(int table_size) { - _table_size = table_size; - _buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size, mtSymbol); - for (int index = 0; index < table_size; index++) { - _buckets[index].clear(); - } - } + void initialize_table(int table_size); public: diff --git a/src/hotspot/share/oops/generateOopMap.cpp b/src/hotspot/share/oops/generateOopMap.cpp index e8edb2c0030..50d4de01f4f 100644 --- a/src/hotspot/share/oops/generateOopMap.cpp +++ b/src/hotspot/share/oops/generateOopMap.cpp @@ -27,6 +27,7 @@ #include "interpreter/bytecodeStream.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" +#include "memory/allocation.inline.hpp" #include "oops/generateOopMap.hpp" #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" @@ -217,6 +218,12 @@ public: int RetTable::_init_nof_entries = 10; int RetTableEntry::_init_nof_jsrs = 5; +RetTableEntry::RetTableEntry(int target, RetTableEntry *next) { + _target_bci = target; + _jsrs = new GrowableArray(_init_nof_jsrs); + _next = next; +} + void RetTableEntry::add_delta(int bci, int delta) { if (_target_bci > bci) _target_bci += delta; diff --git a/src/hotspot/share/oops/generateOopMap.hpp b/src/hotspot/share/oops/generateOopMap.hpp index e401746240a..3fa44525146 100644 --- a/src/hotspot/share/oops/generateOopMap.hpp +++ b/src/hotspot/share/oops/generateOopMap.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_OOPS_GENERATEOOPMAP_HPP #include "interpreter/bytecodeStream.hpp" -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "memory/universe.inline.hpp" #include "oops/method.hpp" #include "oops/oopsHierarchy.hpp" @@ -57,7 +57,7 @@ class RetTableEntry : public ResourceObj { GrowableArray * _jsrs; // List of return addresses (bytecode index) RetTableEntry *_next; // Link to next entry public: - RetTableEntry(int target, RetTableEntry *next) { _target_bci=target; _jsrs = new GrowableArray(_init_nof_jsrs); _next = next; } + RetTableEntry(int target, RetTableEntry *next); // Query int target_bci() const { return _target_bci; } diff --git a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp index cb416918d9e..a00d5b14951 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp @@ -71,10 +71,15 @@ void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) { Devirtualizer::do_klass(closure, klass); } } else { - // If klass is NULL then this a mirror for a primitive type. - // We don't have to follow them, since they are handled as strong - // roots in Universe::oops_do. - assert(java_lang_Class::is_primitive(obj), "Sanity check"); + // We would like to assert here (as below) that if klass has been NULL, then + // this has been a mirror for a primitive type that we do not need to follow + // as they are always strong roots. + // However, we might get across a klass that just changed during CMS concurrent + // marking if allocation occurred in the old generation. + // This is benign here, as we keep alive all CLDs that were loaded during the + // CMS concurrent phase in the class loading, i.e. they will be iterated over + // and kept alive during remark. + // assert(java_lang_Class::is_primitive(obj), "Sanity check"); } } diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index e1c859c3af9..9f105299402 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -740,6 +740,14 @@ \ develop(bool, RenumberLiveNodes, true, \ "Renumber live nodes") \ + \ + product(uintx, LoopStripMiningIter, 0, \ + "Number of iterations in strip mined loop") \ + range(0, max_juint) \ + \ + product(uintx, LoopStripMiningIterShortLoop, 0, \ + "Loop with fewer iterations are not strip mined") \ + range(0, max_juint) \ C2_FLAGS(DECLARE_DEVELOPER_FLAG, \ DECLARE_PD_DEVELOPER_FLAG, \ diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 272c1340fbb..e2269104bf7 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -571,6 +571,18 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) { return NULL; } else if (can_reshape) { // Optimization phase - remove the node PhaseIterGVN *igvn = phase->is_IterGVN(); + // Strip mined (inner) loop is going away, remove outer loop. + if (is_CountedLoop() && + as_Loop()->is_strip_mined()) { + Node* outer_sfpt = as_CountedLoop()->outer_safepoint(); + Node* outer_out = as_CountedLoop()->outer_loop_exit(); + if (outer_sfpt != NULL && outer_out != NULL) { + Node* in = outer_sfpt->in(0); + igvn->replace_node(outer_out, in); + LoopNode* outer = as_CountedLoop()->outer_loop(); + igvn->replace_input_of(outer, LoopNode::LoopBackControl, igvn->C->top()); + } + } Node *parent_ctrl; if( cnt == 0 ) { assert( req() == 1, "no inputs expected" ); diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index 123ea3e0f28..235021f8660 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -133,6 +133,8 @@ macro(ConvL2F) macro(ConvL2I) macro(CountedLoop) macro(CountedLoopEnd) +macro(OuterStripMinedLoop) +macro(OuterStripMinedLoopEnd) macro(CountLeadingZerosI) macro(CountLeadingZerosL) macro(CountTrailingZerosI) @@ -252,6 +254,7 @@ macro(SafePoint) macro(SafePointScalarObject) macro(SCMemProj) macro(SqrtD) +macro(SqrtF) macro(Start) macro(StartOSR) macro(StoreB) @@ -320,6 +323,7 @@ macro(AbsVD) macro(NegVF) macro(NegVD) macro(SqrtVD) +macro(SqrtVF) macro(LShiftCntV) macro(RShiftCntV) macro(LShiftVB) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 6fe374640b6..8e5da8a4028 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -2751,27 +2751,28 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { case Op_CallRuntime: case Op_CallLeaf: case Op_CallLeafNoFP: { - assert( n->is_Call(), "" ); + assert (n->is_Call(), ""); CallNode *call = n->as_Call(); // Count call sites where the FP mode bit would have to be flipped. // Do not count uncommon runtime calls: // uncommon_trap, _complete_monitor_locking, _complete_monitor_unlocking, // _new_Java, _new_typeArray, _new_objArray, _rethrow_Java, ... - if( !call->is_CallStaticJava() || !call->as_CallStaticJava()->_name ) { + if (!call->is_CallStaticJava() || !call->as_CallStaticJava()->_name) { frc.inc_call_count(); // Count the call site } else { // See if uncommon argument is shared Node *n = call->in(TypeFunc::Parms); int nop = n->Opcode(); // Clone shared simple arguments to uncommon calls, item (1). - if( n->outcnt() > 1 && + if (n->outcnt() > 1 && !n->is_Proj() && nop != Op_CreateEx && nop != Op_CheckCastPP && nop != Op_DecodeN && nop != Op_DecodeNKlass && - !n->is_Mem() ) { + !n->is_Mem() && + !n->is_Phi()) { Node *x = n->clone(); - call->set_req( TypeFunc::Parms, x ); + call->set_req(TypeFunc::Parms, x); } } break; @@ -3244,9 +3245,11 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { break; case Op_Loop: case Op_CountedLoop: + case Op_OuterStripMinedLoop: if (n->as_Loop()->is_inner_loop()) { frc.inc_inner_loop_count(); } + n->as_Loop()->verify_strip_mined(0); break; case Op_LShiftI: case Op_RShiftI: @@ -3525,6 +3528,14 @@ bool Compile::final_graph_reshaping() { record_method_not_compilable("infinite loop"); return true; // Found unvisited kid; must be unreach } + + // Here so verification code in final_graph_reshaping_walk() + // always see an OuterStripMinedLoopEnd + if (n->is_OuterStripMinedLoopEnd()) { + IfNode* init_iff = n->as_If(); + Node* iff = new IfNode(init_iff->in(0), init_iff->in(1), init_iff->_prob, init_iff->_fcnt); + n->subsume_by(iff, this); + } } // If original bytecodes contained a mixture of floats and doubles diff --git a/src/hotspot/share/opto/convertnode.cpp b/src/hotspot/share/opto/convertnode.cpp index 5d97a7330f2..aaf0cc2fc61 100644 --- a/src/hotspot/share/opto/convertnode.cpp +++ b/src/hotspot/share/opto/convertnode.cpp @@ -73,6 +73,21 @@ const Type* ConvD2FNode::Value(PhaseGVN* phase) const { return TypeF::make( (float)td->getd() ); } +//------------------------------Ideal------------------------------------------ +// If we see pattern ConvF2D SomeDoubleOp ConvD2F, do operation as float. +Node *ConvD2FNode::Ideal(PhaseGVN *phase, bool can_reshape) { + if ( in(1)->Opcode() == Op_SqrtD ) { + Node* sqrtd = in(1); + if ( sqrtd->in(1)->Opcode() == Op_ConvF2D ) { + if ( Matcher::match_rule_supported(Op_SqrtF) ) { + Node* convf2d = sqrtd->in(1); + return new SqrtFNode(phase->C, sqrtd->in(0), convf2d->in(1)); + } + } + } + return NULL; +} + //------------------------------Identity--------------------------------------- // Float's can be converted to doubles with no loss of bits. Hence // converting a float to a double and back to a float is a NOP. diff --git a/src/hotspot/share/opto/convertnode.hpp b/src/hotspot/share/opto/convertnode.hpp index 0a3e78b18dc..6ae7de5882f 100644 --- a/src/hotspot/share/opto/convertnode.hpp +++ b/src/hotspot/share/opto/convertnode.hpp @@ -51,6 +51,7 @@ class ConvD2FNode : public Node { virtual const Type *bottom_type() const { return Type::FLOAT; } virtual const Type* Value(PhaseGVN* phase) const; virtual Node* Identity(PhaseGVN* phase); + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual uint ideal_reg() const { return Op_RegF; } }; diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index 0d5fbdda39c..cb78db147b2 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, 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,6 +29,7 @@ #include "opto/machnode.hpp" #include "opto/parse.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/threadSMR.hpp" #ifndef PRODUCT @@ -91,8 +92,7 @@ IdealGraphPrinter *IdealGraphPrinter::printer() { } void IdealGraphPrinter::clean_up() { - JavaThread *p; - for (p = Threads::first(); p; p = p->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *p = jtiwh.next(); ) { if (p->is_Compiler_thread()) { CompilerThread *c = (CompilerThread *)p; IdealGraphPrinter *printer = c->ideal_graph_printer(); diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 7865e3ca882..3437dfed372 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -117,6 +117,7 @@ static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { // No intervening control, like a simple Call Node *r = iff->in(0); if( !r->is_Region() ) return NULL; + if (r->is_Loop() && r->in(LoopNode::LoopBackControl)->is_top()) return NULL; // going away anyway if( phi->region() != r ) return NULL; // No other users of the cmp/bool if (b->outcnt() != 1 || cmp->outcnt() != 1) { diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 0de17405ccc..9de54bb372a 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -515,8 +515,8 @@ class Invariance : public StackObj { _visited(area), _invariant(area), _stack(area, 10 /* guess */), _clone_visited(area), _old_new(area) { - Node* head = _lpt->_head; - Node* entry = head->in(LoopNode::EntryControl); + LoopNode* head = _lpt->_head->as_Loop(); + Node* entry = head->skip_strip_mined()->in(LoopNode::EntryControl); if (entry->outcnt() != 1) { // If a node is pinned between the predicates and the loop // entry, we won't be able to move any node in the loop that @@ -801,6 +801,10 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { return false; } + if (head->is_OuterStripMinedLoop()) { + return false; + } + CountedLoopNode *cl = NULL; if (head->is_valid_counted_loop()) { cl = head->as_CountedLoop(); @@ -812,7 +816,7 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { cl = NULL; } - Node* entry = head->in(LoopNode::EntryControl); + Node* entry = head->skip_strip_mined()->in(LoopNode::EntryControl); ProjNode *predicate_proj = NULL; // Loop limit check predicate should be near the loop. predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); @@ -1007,6 +1011,8 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { } #endif + head->verify_strip_mined(1); + return hoisted; } diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 2bad280129a..28a270ef4c4 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -67,6 +67,16 @@ void IdealLoopTree::record_for_igvn() { Node *n = _body.at(i); _phase->_igvn._worklist.push(n); } + // put body of outer strip mined loop on igvn work list as well + if (_head->is_CountedLoop() && _head->as_Loop()->is_strip_mined()) { + CountedLoopNode* l = _head->as_CountedLoop(); + _phase->_igvn._worklist.push(l->outer_loop()); + _phase->_igvn._worklist.push(l->outer_loop_tail()); + _phase->_igvn._worklist.push(l->outer_loop_end()); + _phase->_igvn._worklist.push(l->outer_safepoint()); + Node* cle_out = _head->as_CountedLoop()->loopexit()->proj_out(false); + _phase->_igvn._worklist.push(cle_out); + } } //------------------------------compute_exact_trip_count----------------------- @@ -494,7 +504,7 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { loop->dump_head(); } #endif - Node* head = loop->_head; + LoopNode* head = loop->_head->as_Loop(); bool counted_loop = head->is_CountedLoop(); if (counted_loop) { CountedLoopNode *cl = head->as_CountedLoop(); @@ -514,7 +524,7 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { // Step 1: Clone the loop body. The clone becomes the peeled iteration. // The pre-loop illegally has 2 control users (old & new loops). - clone_loop( loop, old_new, dom_depth(head) ); + clone_loop(loop, old_new, dom_depth(head->skip_strip_mined()), ControlAroundStripMined); // Step 2: Make the old-loop fall-in edges point to the peeled iteration. // Do this by making the old-loop fall-in edges act as if they came @@ -523,8 +533,8 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { // the pre-loop with only 1 user (the new peeled iteration), but the // peeled-loop backedge has 2 users. Node* new_entry = old_new[head->in(LoopNode::LoopBackControl)->_idx]; - _igvn.hash_delete(head); - head->set_req(LoopNode::EntryControl, new_entry); + _igvn.hash_delete(head->skip_strip_mined()); + head->skip_strip_mined()->set_req(LoopNode::EntryControl, new_entry); for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) { Node* old = head->fast_out(j); if (old->in(0) == loop->_head && old->req() == 3 && old->is_Phi()) { @@ -1009,8 +1019,6 @@ void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_ CountedLoopEndNode *main_end = main_head->loopexit(); guarantee(main_end != NULL, "no loop exit node"); assert( main_end->outcnt() == 2, "1 true, 1 false path only" ); - uint dd_main_head = dom_depth(main_head); - uint max = main_head->outcnt(); Node *pre_header= main_head->in(LoopNode::EntryControl); Node *init = main_head->init_trip(); @@ -1043,7 +1051,16 @@ void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_ // Step B1: Clone the loop body. The clone becomes the pre-loop. The main // loop pre-header illegally has 2 control users (old & new loops). - clone_loop( loop, old_new, dd_main_head ); + LoopNode* outer_main_head = main_head; + IdealLoopTree* outer_loop = loop; + if (main_head->is_strip_mined()) { + main_head->verify_strip_mined(1); + outer_main_head = main_head->outer_loop(); + outer_loop = loop->_parent; + assert(outer_loop->_head == outer_main_head, "broken loop tree"); + } + uint dd_main_head = dom_depth(outer_main_head); + clone_loop(loop, old_new, dd_main_head, ControlAroundStripMined); CountedLoopNode* pre_head = old_new[main_head->_idx]->as_CountedLoop(); CountedLoopEndNode* pre_end = old_new[main_end ->_idx]->as_CountedLoopEnd(); pre_head->set_pre_loop(main_head); @@ -1058,7 +1075,7 @@ void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_ IfFalseNode *new_pre_exit = new IfFalseNode(pre_end); _igvn.register_new_node_with_optimizer( new_pre_exit ); set_idom(new_pre_exit, pre_end, dd_main_head); - set_loop(new_pre_exit, loop->_parent); + set_loop(new_pre_exit, outer_loop->_parent); // Step B2: Build a zero-trip guard for the main-loop. After leaving the // pre-loop, the main-loop may not execute at all. Later in life this @@ -1075,22 +1092,22 @@ void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_ IfNode *min_iff = new IfNode( new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN ); _igvn.register_new_node_with_optimizer( min_iff ); set_idom(min_iff, new_pre_exit, dd_main_head); - set_loop(min_iff, loop->_parent); + set_loop(min_iff, outer_loop->_parent); // Plug in the false-path, taken if we need to skip main-loop _igvn.hash_delete( pre_exit ); pre_exit->set_req(0, min_iff); set_idom(pre_exit, min_iff, dd_main_head); - set_idom(pre_exit->unique_out(), min_iff, dd_main_head); + set_idom(pre_exit->unique_ctrl_out(), min_iff, dd_main_head); // Make the true-path, must enter the main loop Node *min_taken = new IfTrueNode( min_iff ); _igvn.register_new_node_with_optimizer( min_taken ); set_idom(min_taken, min_iff, dd_main_head); - set_loop(min_taken, loop->_parent); + set_loop(min_taken, outer_loop->_parent); // Plug in the true path - _igvn.hash_delete( main_head ); - main_head->set_req(LoopNode::EntryControl, min_taken); - set_idom(main_head, min_taken, dd_main_head); + _igvn.hash_delete(outer_main_head); + outer_main_head->set_req(LoopNode::EntryControl, min_taken); + set_idom(outer_main_head, min_taken, dd_main_head); Arena *a = Thread::current()->resource_area(); VectorSet visited(a); @@ -1102,7 +1119,7 @@ void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_ if( main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0 ) { Node *pre_phi = old_new[main_phi->_idx]; Node *fallpre = clone_up_backedge_goo(pre_head->back_control(), - main_head->init_control(), + main_head->skip_strip_mined()->in(LoopNode::EntryControl), pre_phi->in(LoopNode::LoopBackControl), visited, clones); _igvn.hash_delete(main_phi); @@ -1305,16 +1322,24 @@ void PhaseIdealLoop::insert_scalar_rced_post_loop(IdealLoopTree *loop, Node_List Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new, CountedLoopNode *main_head, CountedLoopEndNode *main_end, Node *incr, Node *limit, CountedLoopNode *&post_head) { + IfNode* outer_main_end = main_end; + IdealLoopTree* outer_loop = loop; + if (main_head->is_strip_mined()) { + main_head->verify_strip_mined(1); + outer_main_end = main_head->outer_loop_end(); + outer_loop = loop->_parent; + assert(outer_loop->_head == main_head->in(LoopNode::EntryControl), "broken loop tree"); + } //------------------------------ // Step A: Create a new post-Loop. - Node* main_exit = main_end->proj_out(false); + Node* main_exit = outer_main_end->proj_out(false); assert(main_exit->Opcode() == Op_IfFalse, ""); int dd_main_exit = dom_depth(main_exit); // Step A1: Clone the loop body of main. The clone becomes the post-loop. // The main loop pre-header illegally has 2 control users (old & new loops). - clone_loop(loop, old_new, dd_main_exit); + clone_loop(loop, old_new, dd_main_exit, ControlAroundStripMined); assert(old_new[main_end->_idx]->Opcode() == Op_CountedLoopEnd, ""); post_head = old_new[main_head->_idx]->as_CountedLoop(); post_head->set_normal_loop(); @@ -1325,10 +1350,10 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new, post_end->_prob = PROB_FAIR; // Build the main-loop normal exit. - IfFalseNode *new_main_exit = new IfFalseNode(main_end); + IfFalseNode *new_main_exit = new IfFalseNode(outer_main_end); _igvn.register_new_node_with_optimizer(new_main_exit); - set_idom(new_main_exit, main_end, dd_main_exit); - set_loop(new_main_exit, loop->_parent); + set_idom(new_main_exit, outer_main_end, dd_main_exit); + set_loop(new_main_exit, outer_loop->_parent); // Step A2: Build a zero-trip guard for the post-loop. After leaving the // main-loop, the post-loop may not execute at all. We 'opaque' the incr @@ -1346,7 +1371,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new, IfNode *zer_iff = new IfNode(new_main_exit, zer_bol, PROB_FAIR, COUNT_UNKNOWN); _igvn.register_new_node_with_optimizer(zer_iff); set_idom(zer_iff, new_main_exit, dd_main_exit); - set_loop(zer_iff, loop->_parent); + set_loop(zer_iff, outer_loop->_parent); // Plug in the false-path, taken if we need to skip this post-loop _igvn.replace_input_of(main_exit, 0, zer_iff); @@ -1356,7 +1381,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new, Node *zer_taken = new IfTrueNode(zer_iff); _igvn.register_new_node_with_optimizer(zer_taken); set_idom(zer_taken, zer_iff, dd_main_exit); - set_loop(zer_taken, loop->_parent); + set_loop(zer_taken, outer_loop->_parent); // Plug in the true path _igvn.hash_delete(post_head); post_head->set_req(LoopNode::EntryControl, zer_taken); @@ -1431,7 +1456,7 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad // if rounds of unroll,optimize are making progress loop_head->set_node_count_before_unroll(loop->_body.size()); - Node *ctrl = loop_head->in(LoopNode::EntryControl); + Node *ctrl = loop_head->skip_strip_mined()->in(LoopNode::EntryControl); Node *limit = loop_head->limit(); Node *init = loop_head->init_trip(); Node *stride = loop_head->stride(); @@ -1610,7 +1635,7 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad // represents the odd iterations; since the loop trips an even number of // times its backedge is never taken. Kill the backedge. uint dd = dom_depth(loop_head); - clone_loop( loop, old_new, dd ); + clone_loop(loop, old_new, dd, IgnoreStripMined); // Make backedges of the clone equal to backedges of the original. // Make the fall-in from the original come from the fall-out of the clone. @@ -1653,6 +1678,7 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad } loop->record_for_igvn(); + loop_head->clear_strip_mined(); #ifndef PRODUCT if (C->do_vector_loop() && (PrintOpto && (VerifyLoopOptimizations || TraceLoopOpts))) { @@ -2047,7 +2073,7 @@ int PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) { } // Need to find the main-loop zero-trip guard - Node *ctrl = cl->in(LoopNode::EntryControl); + Node *ctrl = cl->skip_strip_mined()->in(LoopNode::EntryControl); Node *iffm = ctrl->in(0); Node *opqzm = iffm->in(1)->in(1)->in(2); assert(opqzm->in(1) == main_limit, "do not understand situation"); @@ -2413,7 +2439,6 @@ bool PhaseIdealLoop::multi_version_post_loops(IdealLoopTree *rce_loop, IdealLoop _igvn.register_new_node_with_optimizer(cur_min); Node *cmp_node = rce_loop_end->cmp_node(); _igvn.replace_input_of(cmp_node, 2, cur_min); - set_idom(cmp_node, cur_min, dom_depth(ctrl)); set_ctrl(cur_min, ctrl); set_loop(cur_min, rce_loop->_parent); @@ -2519,7 +2544,7 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) { #ifdef ASSERT static CountedLoopNode* locate_pre_from_main(CountedLoopNode *cl) { - Node *ctrl = cl->in(LoopNode::EntryControl); + Node *ctrl = cl->skip_strip_mined()->in(LoopNode::EntryControl); assert(ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, ""); Node *iffm = ctrl->in(0); assert(iffm->Opcode() == Op_If, ""); @@ -2558,7 +2583,7 @@ void IdealLoopTree::remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop * } assert(locate_pre_from_main(main_head) == cl, "bad main loop"); - Node* main_iff = main_head->in(LoopNode::EntryControl)->in(0); + Node* main_iff = main_head->skip_strip_mined()->in(LoopNode::EntryControl)->in(0); // Remove the Opaque1Node of the pre loop and make it execute all iterations phase->_igvn.replace_input_of(pre_cmp, 2, pre_cmp->in(2)->in(2)); @@ -2619,7 +2644,7 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) { } if (needs_guard) { // Check for an obvious zero trip guard. - Node* inctrl = PhaseIdealLoop::skip_loop_predicates(cl->in(LoopNode::EntryControl)); + Node* inctrl = PhaseIdealLoop::skip_loop_predicates(cl->skip_strip_mined()->in(LoopNode::EntryControl)); if (inctrl->Opcode() == Op_IfTrue || inctrl->Opcode() == Op_IfFalse) { bool maybe_swapped = (inctrl->Opcode() == Op_IfFalse); // The test should look like just the backedge of a CountedLoop @@ -3167,6 +3192,8 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) { return false; } + head->verify_strip_mined(1); + // Check that the body only contains a store of a loop invariant // value that is indexed by the loop phi. Node* store = NULL; @@ -3288,6 +3315,16 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) { } */ + if (head->is_strip_mined()) { + // Inner strip mined loop goes away so get rid of outer strip + // mined loop + Node* outer_sfpt = head->outer_safepoint(); + Node* in = outer_sfpt->in(0); + Node* outer_out = head->outer_loop_exit(); + lazy_replace(outer_out, in); + _igvn.replace_input_of(outer_sfpt, 0, C->top()); + } + // Redirect the old control and memory edges that are outside the loop. // Sometimes the memory phi of the head is used as the outgoing // state of the loop. It's safe in this case to replace it with the diff --git a/src/hotspot/share/opto/loopUnswitch.cpp b/src/hotspot/share/opto/loopUnswitch.cpp index 72201c2e282..9940b333fe0 100644 --- a/src/hotspot/share/opto/loopUnswitch.cpp +++ b/src/hotspot/share/opto/loopUnswitch.cpp @@ -132,11 +132,11 @@ void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) { head->as_CountedLoop()->set_normal_loop(); } - ProjNode* proj_true = create_slow_version_of_loop(loop, old_new, unswitch_iff->Opcode()); + ProjNode* proj_true = create_slow_version_of_loop(loop, old_new, unswitch_iff->Opcode(), CloneIncludesStripMined); #ifdef ASSERT Node* uniqc = proj_true->unique_ctrl_out(); - Node* entry = head->in(LoopNode::EntryControl); + Node* entry = head->skip_strip_mined()->in(LoopNode::EntryControl); Node* predicate = find_predicate(entry); if (predicate != NULL && UseLoopPredicate) { // We may have two predicates, find first. @@ -145,7 +145,8 @@ void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) { } if (predicate != NULL) predicate = predicate->in(0); assert(proj_true->is_IfTrue() && - (predicate == NULL && uniqc == head || + (predicate == NULL && uniqc == head && !head->is_strip_mined() || + predicate == NULL && uniqc == head->in(LoopNode::EntryControl) && head->is_strip_mined() || predicate != NULL && uniqc == predicate), "by construction"); #endif // Increment unswitch count @@ -223,13 +224,16 @@ void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) { // Return control projection of the entry to the fast version. ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop, Node_List &old_new, - int opcode) { + int opcode, + CloneLoopMode mode) { LoopNode* head = loop->_head->as_Loop(); bool counted_loop = head->is_CountedLoop(); - Node* entry = head->in(LoopNode::EntryControl); + Node* entry = head->skip_strip_mined()->in(LoopNode::EntryControl); _igvn.rehash_node_delayed(entry); IdealLoopTree* outer_loop = loop->_parent; + head->verify_strip_mined(1); + Node *cont = _igvn.intcon(1); set_ctrl(cont, C->root()); Node* opq = new Opaque1Node(C, cont); @@ -247,19 +251,21 @@ ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop, // Clone the loop body. The clone becomes the fast loop. The // original pre-header will (illegally) have 3 control users // (old & new loops & new if). - clone_loop(loop, old_new, dom_depth(head), iff); + clone_loop(loop, old_new, dom_depth(head->skip_strip_mined()), mode, iff); assert(old_new[head->_idx]->is_Loop(), "" ); // Fast (true) control Node* iffast_pred = clone_loop_predicates(entry, iffast, !counted_loop); - _igvn.replace_input_of(head, LoopNode::EntryControl, iffast_pred); - set_idom(head, iffast_pred, dom_depth(head)); // Slow (false) control Node* ifslow_pred = clone_loop_predicates(entry, ifslow, !counted_loop); - LoopNode* slow_head = old_new[head->_idx]->as_Loop(); - _igvn.replace_input_of(slow_head, LoopNode::EntryControl, ifslow_pred); - set_idom(slow_head, ifslow_pred, dom_depth(slow_head)); + + Node* l = head->skip_strip_mined(); + _igvn.replace_input_of(l, LoopNode::EntryControl, iffast_pred); + set_idom(l, iffast_pred, dom_depth(l)); + LoopNode* slow_l = old_new[head->_idx]->as_Loop()->skip_strip_mined(); + _igvn.replace_input_of(slow_l, LoopNode::EntryControl, ifslow_pred); + set_idom(slow_l, ifslow_pred, dom_depth(l)); recompute_dom_depth(); @@ -270,9 +276,9 @@ LoopNode* PhaseIdealLoop::create_reserve_version_of_loop(IdealLoopTree *loop, Co Node_List old_new; LoopNode* head = loop->_head->as_Loop(); bool counted_loop = head->is_CountedLoop(); - Node* entry = head->in(LoopNode::EntryControl); + Node* entry = head->skip_strip_mined()->in(LoopNode::EntryControl); _igvn.rehash_node_delayed(entry); - IdealLoopTree* outer_loop = loop->_parent; + IdealLoopTree* outer_loop = head->is_strip_mined() ? loop->_parent->_parent : loop->_parent; ConINode* const_1 = _igvn.intcon(1); set_ctrl(const_1, C->root()); @@ -286,7 +292,7 @@ LoopNode* PhaseIdealLoop::create_reserve_version_of_loop(IdealLoopTree *loop, Co // Clone the loop body. The clone becomes the fast loop. The // original pre-header will (illegally) have 3 control users // (old & new loops & new if). - clone_loop(loop, old_new, dom_depth(head), iff); + clone_loop(loop, old_new, dom_depth(head), CloneIncludesStripMined, iff); assert(old_new[head->_idx]->is_Loop(), "" ); LoopNode* slow_head = old_new[head->_idx]->as_Loop(); @@ -303,9 +309,9 @@ LoopNode* PhaseIdealLoop::create_reserve_version_of_loop(IdealLoopTree *loop, Co #endif // Fast (true) control - _igvn.replace_input_of(head, LoopNode::EntryControl, iffast); + _igvn.replace_input_of(head->skip_strip_mined(), LoopNode::EntryControl, iffast); // Slow (false) control - _igvn.replace_input_of(slow_head, LoopNode::EntryControl, ifslow); + _igvn.replace_input_of(slow_head->skip_strip_mined(), LoopNode::EntryControl, ifslow); recompute_dom_depth(); @@ -394,7 +400,7 @@ bool CountedLoopReserveKit::create_reserve() { return false; } - Node* ifslow_pred = _lp_reserved->as_CountedLoop()->in(LoopNode::EntryControl); + Node* ifslow_pred = _lp_reserved->skip_strip_mined()->in(LoopNode::EntryControl); if (!ifslow_pred->is_IfFalse()) { return false; diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 5f003d304ff..1e5af607642 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -261,8 +261,68 @@ void PhaseIdealLoop::set_subtree_ctrl( Node *n ) { set_early_ctrl( n ); } +// Create a skeleton strip mined outer loop: a Loop head before the +// inner strip mined loop, a safepoint and an exit condition guarded +// by an opaque node after the inner strip mined loop with a backedge +// to the loop head. The inner strip mined loop is left as it is. Only +// once loop optimizations are over, do we adjust the inner loop exit +// condition to limit its number of iterations, set the outer loop +// exit condition and add Phis to the outer loop head. Some loop +// optimizations that operate on the inner strip mined loop need to be +// aware of the outer strip mined loop: loop unswitching needs to +// clone the outer loop as well as the inner, unrolling needs to only +// clone the inner loop etc. No optimizations need to change the outer +// strip mined loop as it is only a skeleton. +IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, + IdealLoopTree* loop, float cl_prob, float le_fcnt, + Node*& entry_control, Node*& iffalse) { + Node* outer_test = _igvn.intcon(0); + set_ctrl(outer_test, C->root()); + Node *orig = iffalse; + iffalse = iffalse->clone(); + _igvn.register_new_node_with_optimizer(iffalse); + set_idom(iffalse, idom(orig), dom_depth(orig)); + + IfNode *outer_le = new OuterStripMinedLoopEndNode(iffalse, outer_test, cl_prob, le_fcnt); + Node *outer_ift = new IfTrueNode (outer_le); + Node* outer_iff = orig; + _igvn.replace_input_of(outer_iff, 0, outer_le); + + LoopNode *outer_l = new OuterStripMinedLoopNode(C, init_control, outer_ift); + entry_control = outer_l; + + IdealLoopTree* outer_ilt = new IdealLoopTree(this, outer_l, outer_ift); + IdealLoopTree* parent = loop->_parent; + IdealLoopTree* sibling = parent->_child; + if (sibling == loop) { + parent->_child = outer_ilt; + } else { + while (sibling->_next != loop) { + sibling = sibling->_next; + } + sibling->_next = outer_ilt; + } + outer_ilt->_next = loop->_next; + outer_ilt->_parent = parent; + outer_ilt->_child = loop; + outer_ilt->_nest = loop->_nest; + loop->_parent = outer_ilt; + loop->_next = NULL; + loop->_nest++; + + set_loop(iffalse, outer_ilt); + register_control(outer_le, outer_ilt, iffalse); + register_control(outer_ift, outer_ilt, outer_le); + set_idom(outer_iff, outer_le, dom_depth(outer_le)); + _igvn.register_new_node_with_optimizer(outer_l); + set_loop(outer_l, outer_ilt); + set_idom(outer_l, init_control, dom_depth(init_control)+1); + + return outer_ilt; +} + //------------------------------is_counted_loop-------------------------------- -bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { +bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*& loop) { PhaseGVN *gvn = &_igvn; // Counted loop head must be a good RegionNode with only 3 not NULL @@ -280,7 +340,7 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { // Allow funny placement of Safepoint if (back_control->Opcode() == Op_SafePoint) { - if (UseCountedLoopSafepoints) { + if (LoopStripMiningIter != 0) { // Leaving the safepoint on the backedge and creating a // CountedLoop will confuse optimizations. We can't move the // safepoint around because its jvm state wouldn't match a new @@ -600,7 +660,7 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { } set_subtree_ctrl( limit ); - if (!UseCountedLoopSafepoints) { + if (LoopStripMiningIter == 0) { // Check for SafePoint on backedge and remove Node *sfpt = x->in(LoopNode::LoopBackControl); if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) { @@ -683,8 +743,20 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { assert(iff->outcnt() == 0, "should be dead now"); lazy_replace( iff, le ); // fix 'get_ctrl' + Node *sfpt2 = le->in(0); + + Node* entry_control = init_control; + bool strip_mine_loop = LoopStripMiningIter > 1 && loop->_child == NULL && + sfpt2->Opcode() == Op_SafePoint && !loop->_has_call; + IdealLoopTree* outer_ilt = NULL; + if (strip_mine_loop) { + outer_ilt = create_outer_strip_mined_loop(test, cmp, init_control, loop, + cl_prob, le->_fcnt, entry_control, + iffalse); + } + // Now setup a new CountedLoopNode to replace the existing LoopNode - CountedLoopNode *l = new CountedLoopNode(init_control, back_control); + CountedLoopNode *l = new CountedLoopNode(entry_control, back_control); l->set_unswitch_count(x->as_Loop()->unswitch_count()); // Preserve // The following assert is approximately true, and defines the intention // of can_be_counted_loop. It fails, however, because phase->type @@ -696,12 +768,19 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { // Fix all data nodes placed at the old loop head. // Uses the lazy-update mechanism of 'get_ctrl'. lazy_replace( x, l ); - set_idom(l, init_control, dom_depth(x)); + set_idom(l, entry_control, dom_depth(entry_control) + 1); - if (!UseCountedLoopSafepoints) { + if (LoopStripMiningIter == 0 || strip_mine_loop) { // Check for immediately preceding SafePoint and remove - Node *sfpt2 = le->in(0); - if (sfpt2->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt2)) { + if (sfpt2->Opcode() == Op_SafePoint && (LoopStripMiningIter != 0 || is_deleteable_safept(sfpt2))) { + if (strip_mine_loop) { + Node* outer_le = outer_ilt->_tail->in(0); + Node* sfpt = sfpt2->clone(); + sfpt->set_req(0, iffalse); + outer_le->set_req(0, sfpt); + register_control(sfpt, outer_ilt, iffalse); + set_idom(outer_le, sfpt, dom_depth(sfpt)); + } lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control)); if (loop->_safepts != NULL) { loop->_safepts->yank(sfpt2); @@ -730,6 +809,13 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { // bounds l->phi()->as_Phi()->set_type(l->phi()->Value(&_igvn)); + if (strip_mine_loop) { + l->mark_strip_mined(); + l->verify_strip_mined(1); + outer_ilt->_head->as_Loop()->verify_strip_mined(1); + loop = outer_ilt; + } + return true; } @@ -776,12 +862,93 @@ Node* PhaseIdealLoop::exact_limit( IdealLoopTree *loop ) { // Return a node which is more "ideal" than the current node. // Attempt to convert into a counted-loop. Node *LoopNode::Ideal(PhaseGVN *phase, bool can_reshape) { - if (!can_be_counted_loop(phase)) { + if (!can_be_counted_loop(phase) && !is_OuterStripMinedLoop()) { phase->C->set_major_progress(); } return RegionNode::Ideal(phase, can_reshape); } +void LoopNode::verify_strip_mined(int expect_skeleton) const { +#ifdef ASSERT + const OuterStripMinedLoopNode* outer = NULL; + const CountedLoopNode* inner = NULL; + if (is_strip_mined()) { + assert(is_CountedLoop(), "no Loop should be marked strip mined"); + inner = as_CountedLoop(); + outer = inner->in(LoopNode::EntryControl)->as_OuterStripMinedLoop(); + } else if (is_OuterStripMinedLoop()) { + outer = this->as_OuterStripMinedLoop(); + inner = outer->unique_ctrl_out()->as_CountedLoop(); + assert(!is_strip_mined(), "outer loop shouldn't be marked strip mined"); + } + if (inner != NULL || outer != NULL) { + assert(inner != NULL && outer != NULL, "missing loop in strip mined nest"); + Node* outer_tail = outer->in(LoopNode::LoopBackControl); + Node* outer_le = outer_tail->in(0); + assert(outer_le->Opcode() == Op_OuterStripMinedLoopEnd, "tail of outer loop should be an If"); + Node* sfpt = outer_le->in(0); + assert(sfpt->Opcode() == Op_SafePoint, "where's the safepoint?"); + Node* inner_out = sfpt->in(0); + if (inner_out->outcnt() != 1) { + ResourceMark rm; + Unique_Node_List wq; + + for (DUIterator_Fast imax, i = inner_out->fast_outs(imax); i < imax; i++) { + Node* u = inner_out->fast_out(i); + if (u == sfpt) { + continue; + } + wq.clear(); + wq.push(u); + bool found_sfpt = false; + for (uint next = 0; next < wq.size() && !found_sfpt; next++) { + Node *n = wq.at(next); + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax && !found_sfpt; i++) { + Node* u = n->fast_out(i); + if (u == sfpt) { + found_sfpt = true; + } + if (!u->is_CFG()) { + wq.push(u); + } + } + } + assert(found_sfpt, "no node in loop that's not input to safepoint"); + } + } + CountedLoopEndNode* cle = inner_out->in(0)->as_CountedLoopEnd(); + assert(cle == inner->loopexit(), "mismatch"); + bool has_skeleton = outer_le->in(1)->bottom_type()->singleton() && outer_le->in(1)->bottom_type()->is_int()->get_con() == 0; + if (has_skeleton) { + assert(expect_skeleton == 1 || expect_skeleton == -1, "unexpected skeleton node"); + assert(outer->outcnt() == 2, "only phis"); + } else { + assert(expect_skeleton == 0 || expect_skeleton == -1, "no skeleton node?"); + uint phis = 0; + for (DUIterator_Fast imax, i = inner->fast_outs(imax); i < imax; i++) { + Node* u = inner->fast_out(i); + if (u->is_Phi()) { + phis++; + } + } + for (DUIterator_Fast imax, i = outer->fast_outs(imax); i < imax; i++) { + Node* u = outer->fast_out(i); + assert(u == outer || u == inner || u->is_Phi(), "nothing between inner and outer loop"); + } + uint stores = 0; + for (DUIterator_Fast imax, i = inner_out->fast_outs(imax); i < imax; i++) { + Node* u = inner_out->fast_out(i); + if (u->is_Store()) { + stores++; + } + } + assert(outer->outcnt() >= phis + 2 && outer->outcnt() <= phis + 2 + stores + 1, "only phis"); + } + assert(sfpt->outcnt() == 1, "no data node"); + assert(outer_tail->outcnt() == 1 || !has_skeleton, "no data node"); + } +#endif +} //============================================================================= //------------------------------Ideal------------------------------------------ @@ -802,6 +969,7 @@ void CountedLoopNode::dump_spec(outputStream *st) const { if (is_pre_loop ()) st->print("pre of N%d" , _main_idx); if (is_main_loop()) st->print("main of N%d", _idx); if (is_post_loop()) st->print("post of N%d", _main_idx); + if (is_strip_mined()) st->print(" strip mined"); } #endif @@ -990,6 +1158,365 @@ Node* CountedLoopNode::match_incr_with_optional_truncation( return NULL; } +LoopNode* CountedLoopNode::skip_strip_mined(int expect_opaq) { + if (is_strip_mined()) { + verify_strip_mined(expect_opaq); + return in(EntryControl)->as_Loop(); + } + return this; +} + +OuterStripMinedLoopNode* CountedLoopNode::outer_loop() const { + assert(is_strip_mined(), "not a strip mined loop"); + Node* c = in(EntryControl); + if (c == NULL || c->is_top() || !c->is_OuterStripMinedLoop()) { + return NULL; + } + return c->as_OuterStripMinedLoop(); +} + +IfTrueNode* OuterStripMinedLoopNode::outer_loop_tail() const { + Node* c = in(LoopBackControl); + if (c == NULL || c->is_top()) { + return NULL; + } + return c->as_IfTrue(); +} + +IfTrueNode* CountedLoopNode::outer_loop_tail() const { + LoopNode* l = outer_loop(); + if (l == NULL) { + return NULL; + } + return l->outer_loop_tail(); +} + +OuterStripMinedLoopEndNode* OuterStripMinedLoopNode::outer_loop_end() const { + IfTrueNode* proj = outer_loop_tail(); + if (proj == NULL) { + return NULL; + } + Node* c = proj->in(0); + if (c == NULL || c->is_top() || c->outcnt() != 2) { + return NULL; + } + return c->as_OuterStripMinedLoopEnd(); +} + +OuterStripMinedLoopEndNode* CountedLoopNode::outer_loop_end() const { + LoopNode* l = outer_loop(); + if (l == NULL) { + return NULL; + } + return l->outer_loop_end(); +} + +IfFalseNode* OuterStripMinedLoopNode::outer_loop_exit() const { + IfNode* le = outer_loop_end(); + if (le == NULL) { + return NULL; + } + Node* c = le->proj_out(false); + if (c == NULL) { + return NULL; + } + return c->as_IfFalse(); +} + +IfFalseNode* CountedLoopNode::outer_loop_exit() const { + LoopNode* l = outer_loop(); + if (l == NULL) { + return NULL; + } + return l->outer_loop_exit(); +} + +SafePointNode* OuterStripMinedLoopNode::outer_safepoint() const { + IfNode* le = outer_loop_end(); + if (le == NULL) { + return NULL; + } + Node* c = le->in(0); + if (c == NULL || c->is_top()) { + return NULL; + } + assert(c->Opcode() == Op_SafePoint, "broken outer loop"); + return c->as_SafePoint(); +} + +SafePointNode* CountedLoopNode::outer_safepoint() const { + LoopNode* l = outer_loop(); + if (l == NULL) { + return NULL; + } + return l->outer_safepoint(); +} + +void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { + // Look for the outer & inner strip mined loop, reduce number of + // iterations of the inner loop, set exit condition of outer loop, + // construct required phi nodes for outer loop. + CountedLoopNode* inner_cl = unique_ctrl_out()->as_CountedLoop(); + assert(inner_cl->is_strip_mined(), "inner loop should be strip mined"); + Node* inner_iv_phi = inner_cl->phi(); + if (inner_iv_phi == NULL) { + return; + } + CountedLoopEndNode* inner_cle = inner_cl->loopexit(); + + int stride = inner_cl->stride_con(); + jlong scaled_iters_long = ((jlong)LoopStripMiningIter) * ABS(stride); + int scaled_iters = (int)scaled_iters_long; + int short_scaled_iters = LoopStripMiningIterShortLoop* ABS(stride); + const TypeInt* inner_iv_t = igvn->type(inner_iv_phi)->is_int(); + jlong iter_estimate = (jlong)inner_iv_t->_hi - (jlong)inner_iv_t->_lo; + assert(iter_estimate > 0, "broken"); + if ((jlong)scaled_iters != scaled_iters_long || iter_estimate <= short_scaled_iters) { + // Remove outer loop and safepoint (too few iterations) + Node* outer_sfpt = outer_safepoint(); + Node* outer_out = outer_loop_exit(); + igvn->replace_node(outer_out, outer_sfpt->in(0)); + igvn->replace_input_of(outer_sfpt, 0, igvn->C->top()); + inner_cl->clear_strip_mined(); + return; + } + if (iter_estimate <= scaled_iters_long) { + // We would only go through one iteration of + // the outer loop: drop the outer loop but + // keep the safepoint so we don't run for + // too long without a safepoint + IfNode* outer_le = outer_loop_end(); + Node* iff = igvn->transform(new IfNode(outer_le->in(0), outer_le->in(1), outer_le->_prob, outer_le->_fcnt)); + igvn->replace_node(outer_le, iff); + inner_cl->clear_strip_mined(); + return; + } + + Node* cle_tail = inner_cle->proj_out(true); + ResourceMark rm; + Node_List old_new; + if (cle_tail->outcnt() > 1) { + // Look for nodes on backedge of inner loop and clone them + Unique_Node_List backedge_nodes; + for (DUIterator_Fast imax, i = cle_tail->fast_outs(imax); i < imax; i++) { + Node* u = cle_tail->fast_out(i); + if (u != inner_cl) { + assert(!u->is_CFG(), "control flow on the backedge?"); + backedge_nodes.push(u); + } + } + uint last = igvn->C->unique(); + for (uint next = 0; next < backedge_nodes.size(); next++) { + Node* n = backedge_nodes.at(next); + old_new.map(n->_idx, n->clone()); + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* u = n->fast_out(i); + assert(!u->is_CFG(), "broken"); + if (u->_idx >= last) { + continue; + } + if (!u->is_Phi()) { + backedge_nodes.push(u); + } else { + assert(u->in(0) == inner_cl, "strange phi on the backedge"); + } + } + } + // Put the clones on the outer loop backedge + Node* le_tail = outer_loop_tail(); + for (uint next = 0; next < backedge_nodes.size(); next++) { + Node *n = old_new[backedge_nodes.at(next)->_idx]; + for (uint i = 1; i < n->req(); i++) { + if (n->in(i) != NULL && old_new[n->in(i)->_idx] != NULL) { + n->set_req(i, old_new[n->in(i)->_idx]); + } + } + if (n->in(0) != NULL) { + assert(n->in(0) == cle_tail, "node not on backedge?"); + n->set_req(0, le_tail); + } + igvn->register_new_node_with_optimizer(n); + } + } + + Node* iv_phi = NULL; + // Make a clone of each phi in the inner loop + // for the outer loop + for (uint i = 0; i < inner_cl->outcnt(); i++) { + Node* u = inner_cl->raw_out(i); + if (u->is_Phi()) { + assert(u->in(0) == inner_cl, "inconsistent"); + Node* phi = u->clone(); + phi->set_req(0, this); + Node* be = old_new[phi->in(LoopNode::LoopBackControl)->_idx]; + if (be != NULL) { + phi->set_req(LoopNode::LoopBackControl, be); + } + phi = igvn->transform(phi); + igvn->replace_input_of(u, LoopNode::EntryControl, phi); + if (u == inner_iv_phi) { + iv_phi = phi; + } + } + } + Node* cle_out = inner_cle->proj_out(false); + if (cle_out->outcnt() > 1) { + // Look for chains of stores that were sunk + // out of the inner loop and are in the outer loop + for (DUIterator_Fast imax, i = cle_out->fast_outs(imax); i < imax; i++) { + Node* u = cle_out->fast_out(i); + if (u->is_Store()) { + Node* first = u; + for(;;) { + Node* next = first->in(MemNode::Memory); + if (!next->is_Store() || next->in(0) != cle_out) { + break; + } + first = next; + } + Node* last = u; + for(;;) { + Node* next = NULL; + for (DUIterator_Fast jmax, j = last->fast_outs(jmax); j < jmax; j++) { + Node* uu = last->fast_out(j); + if (uu->is_Store() && uu->in(0) == cle_out) { + assert(next == NULL, "only one in the outer loop"); + next = uu; + } + } + if (next == NULL) { + break; + } + last = next; + } + Node* phi = NULL; + for (DUIterator_Fast jmax, j = fast_outs(jmax); j < jmax; j++) { + Node* uu = fast_out(j); + if (uu->is_Phi()) { + Node* be = uu->in(LoopNode::LoopBackControl); + while (be->is_Store() && old_new[be->_idx] != NULL) { + ShouldNotReachHere(); + be = be->in(MemNode::Memory); + } + if (be == last || be == first->in(MemNode::Memory)) { + assert(phi == NULL, "only one phi"); + phi = uu; + } + } + } +#ifdef ASSERT + for (DUIterator_Fast jmax, j = fast_outs(jmax); j < jmax; j++) { + Node* uu = fast_out(j); + if (uu->is_Phi() && uu->bottom_type() == Type::MEMORY) { + if (uu->adr_type() == igvn->C->get_adr_type(igvn->C->get_alias_index(u->adr_type()))) { + assert(phi == uu, "what's that phi?"); + } else if (uu->adr_type() == TypePtr::BOTTOM) { + Node* n = uu->in(LoopNode::LoopBackControl); + uint limit = igvn->C->live_nodes(); + uint i = 0; + while (n != uu) { + i++; + assert(i < limit, "infinite loop"); + if (n->is_Proj()) { + n = n->in(0); + } else if (n->is_SafePoint() || n->is_MemBar()) { + n = n->in(TypeFunc::Memory); + } else if (n->is_Phi()) { + n = n->in(1); + } else if (n->is_MergeMem()) { + n = n->as_MergeMem()->memory_at(igvn->C->get_alias_index(u->adr_type())); + } else if (n->is_Store() || n->is_LoadStore() || n->is_ClearArray()) { + n = n->in(MemNode::Memory); + } else { + n->dump(); + ShouldNotReachHere(); + } + } + } + } + } +#endif + if (phi == NULL) { + // If the an entire chains was sunk, the + // inner loop has no phi for that memory + // slice, create one for the outer loop + phi = PhiNode::make(this, first->in(MemNode::Memory), Type::MEMORY, + igvn->C->get_adr_type(igvn->C->get_alias_index(u->adr_type()))); + phi->set_req(LoopNode::LoopBackControl, last); + phi = igvn->transform(phi); + igvn->replace_input_of(first, MemNode::Memory, phi); + } else { + // Or fix the outer loop fix to include + // that chain of stores. + Node* be = phi->in(LoopNode::LoopBackControl); + while (be->is_Store() && old_new[be->_idx] != NULL) { + ShouldNotReachHere(); + be = be->in(MemNode::Memory); + } + if (be == first->in(MemNode::Memory)) { + if (be == phi->in(LoopNode::LoopBackControl)) { + igvn->replace_input_of(phi, LoopNode::LoopBackControl, last); + } else { + igvn->replace_input_of(be, MemNode::Memory, last); + } + } else { +#ifdef ASSERT + if (be == phi->in(LoopNode::LoopBackControl)) { + assert(phi->in(LoopNode::LoopBackControl) == last, ""); + } else { + assert(be->in(MemNode::Memory) == last, ""); + } +#endif + } + } + } + } + } + + if (iv_phi != NULL) { + // Now adjust the inner loop's exit condition + Node* limit = inner_cl->limit(); + Node* sub = NULL; + if (stride > 0) { + sub = igvn->transform(new SubINode(limit, iv_phi)); + } else { + sub = igvn->transform(new SubINode(iv_phi, limit)); + } + Node* min = igvn->transform(new MinINode(sub, igvn->intcon(scaled_iters))); + Node* new_limit = NULL; + if (stride > 0) { + new_limit = igvn->transform(new AddINode(min, iv_phi)); + } else { + new_limit = igvn->transform(new SubINode(iv_phi, min)); + } + igvn->replace_input_of(inner_cle->cmp_node(), 2, new_limit); + Node* cmp = inner_cle->cmp_node()->clone(); + Node* bol = inner_cle->in(CountedLoopEndNode::TestValue)->clone(); + cmp->set_req(2, limit); + bol->set_req(1, igvn->transform(cmp)); + igvn->replace_input_of(outer_loop_end(), 1, igvn->transform(bol)); + } else { + assert(false, "should be able to adjust outer loop"); + IfNode* outer_le = outer_loop_end(); + Node* iff = igvn->transform(new IfNode(outer_le->in(0), outer_le->in(1), outer_le->_prob, outer_le->_fcnt)); + igvn->replace_node(outer_le, iff); + inner_cl->clear_strip_mined(); + } +} + +const Type* OuterStripMinedLoopEndNode::Value(PhaseGVN* phase) const { + if (!in(0)) return Type::TOP; + if (phase->type(in(0)) == Type::TOP) + return Type::TOP; + + return TypeTuple::IFBOTH; +} + +Node *OuterStripMinedLoopEndNode::Ideal(PhaseGVN *phase, bool can_reshape) { + if (remove_dead_region(phase, can_reshape)) return this; + + return NULL; +} //------------------------------filtered_type-------------------------------- // Return a type based on condition control flow @@ -1778,10 +2305,11 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { if (_head->is_Loop()) _head->as_Loop()->set_inner_loop(); } + IdealLoopTree* loop = this; if (_head->is_CountedLoop() || - phase->is_counted_loop(_head, this)) { + phase->is_counted_loop(_head, loop)) { - if (!UseCountedLoopSafepoints) { + if (LoopStripMiningIter == 0 || (LoopStripMiningIter > 1 && _child == NULL)) { // Indicate we do not need a safepoint here _has_sfpt = 1; } @@ -1800,8 +2328,10 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { } // Recursively - if (_child) _child->counted_loop( phase ); - if (_next) _next ->counted_loop( phase ); + assert(loop->_child != this || (loop->_head->as_Loop()->is_OuterStripMinedLoop() && _head->as_CountedLoop()->is_strip_mined()), "what kind of loop was added?"); + assert(loop->_child != this || (loop->_child->_child == NULL && loop->_child->_next == NULL), "would miss some loops"); + if (loop->_child && loop->_child != this) loop->_child->counted_loop(phase); + if (loop->_next) loop->_next ->counted_loop(phase); } #ifndef PRODUCT @@ -1812,7 +2342,7 @@ void IdealLoopTree::dump_head( ) const { tty->print(" "); tty->print("Loop: N%d/N%d ",_head->_idx,_tail->_idx); if (_irreducible) tty->print(" IRREDUCIBLE"); - Node* entry = _head->in(LoopNode::EntryControl); + Node* entry = _head->as_Loop()->skip_strip_mined(-1)->in(LoopNode::EntryControl); Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); if (predicate != NULL ) { tty->print(" limit_check"); @@ -1863,6 +2393,9 @@ void IdealLoopTree::dump_head( ) const { if (Verbose) { tty->print(" body={"); _body.dump_simple(); tty->print(" }"); } + if (_head->as_Loop()->is_strip_mined()) { + tty->print(" strip_mined"); + } tty->cr(); } @@ -3232,7 +3765,7 @@ bool PhaseIdealLoop::is_canonical_loop_entry(CountedLoopNode* cl) { if (!cl->is_main_loop() && !cl->is_post_loop()) { return false; } - Node* ctrl = cl->in(LoopNode::EntryControl); + Node* ctrl = cl->skip_strip_mined()->in(LoopNode::EntryControl); if (ctrl == NULL || (!ctrl->is_IfTrue() && !ctrl->is_IfFalse())) { return false; } @@ -3292,7 +3825,7 @@ Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) { } while(worklist.size() != 0 && LCA != early) { Node* s = worklist.pop(); - if (s->is_Load()) { + if (s->is_Load() || s->Opcode() == Op_SafePoint) { continue; } else if (s->is_MergeMem()) { for (DUIterator_Fast imax, i = s->fast_outs(imax); i < imax; i++) { @@ -3471,6 +4004,38 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N } } +// Verify that no data node is schedules in the outer loop of a strip +// mined loop. +void PhaseIdealLoop::verify_strip_mined_scheduling(Node *n, Node* least) { +#ifdef ASSERT + if (get_loop(least)->_nest == 0) { + return; + } + IdealLoopTree* loop = get_loop(least); + Node* head = loop->_head; + if (head->is_OuterStripMinedLoop()) { + Node* sfpt = head->as_Loop()->outer_safepoint(); + ResourceMark rm; + Unique_Node_List wq; + wq.push(sfpt); + for (uint i = 0; i < wq.size(); i++) { + Node *m = wq.at(i); + for (uint i = 1; i < m->req(); i++) { + Node* nn = m->in(i); + if (nn == n) { + return; + } + if (nn != NULL && has_ctrl(nn) && get_loop(get_ctrl(nn)) == loop) { + wq.push(nn); + } + } + } + ShouldNotReachHere(); + } +#endif +} + + //------------------------------build_loop_late_post--------------------------- // Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping. // Second pass finds latest legal placement, and ideal loop placement. @@ -3580,8 +4145,9 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) { // which can inhibit range check elimination. if (least != early) { Node* ctrl_out = least->unique_ctrl_out(); - if (ctrl_out && ctrl_out->is_CountedLoop() && - least == ctrl_out->in(LoopNode::EntryControl)) { + if (ctrl_out && ctrl_out->is_Loop() && + least == ctrl_out->in(LoopNode::EntryControl) && + (ctrl_out->is_CountedLoop() || ctrl_out->is_OuterStripMinedLoop())) { Node* least_dom = idom(least); if (get_loop(least_dom)->is_member(get_loop(least))) { least = least_dom; @@ -3606,6 +4172,7 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) { // Assign discovered "here or above" point least = find_non_split_ctrl(least); + verify_strip_mined_scheduling(n, least); set_ctrl(n, least); // Collect inner loop bodies diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 70168186cca..7e615de7e29 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -37,6 +37,7 @@ class CountedLoopNode; class IdealLoopTree; class LoopNode; class Node; +class OuterStripMinedLoopEndNode; class PhaseIdealLoop; class CountedLoopReserveKit; class VectorSet; @@ -71,7 +72,8 @@ protected: VectorizedLoop=2048, HasAtomicPostLoop=4096, HasRangeChecks=8192, - IsMultiversioned=16384}; + IsMultiversioned=16384, + StripMined=32768}; char _unswitch_count; enum { _unswitch_max=3 }; char _postloop_flags; @@ -90,6 +92,7 @@ public: int is_partial_peel_loop() const { return _loop_flags & PartialPeelLoop; } void set_partial_peel_loop() { _loop_flags |= PartialPeelLoop; } int partial_peel_has_failed() const { return _loop_flags & PartialPeelFailed; } + int is_strip_mined() const { return _loop_flags & StripMined; } void mark_partial_peel_failed() { _loop_flags |= PartialPeelFailed; } void mark_has_reductions() { _loop_flags |= HasReductions; } @@ -100,6 +103,8 @@ public: void mark_has_atomic_post_loop() { _loop_flags |= HasAtomicPostLoop; } void mark_has_range_checks() { _loop_flags |= HasRangeChecks; } void mark_is_multiversioned() { _loop_flags |= IsMultiversioned; } + void mark_strip_mined() { _loop_flags |= StripMined; } + void clear_strip_mined() { _loop_flags &= ~StripMined; } int unswitch_max() { return _unswitch_max; } int unswitch_count() { return _unswitch_count; } @@ -131,6 +136,13 @@ public: #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; #endif + + void verify_strip_mined(int expect_skeleton) const; + virtual LoopNode* skip_strip_mined(int expect_opaq = 1) { return this; } + virtual IfTrueNode* outer_loop_tail() const { ShouldNotReachHere(); return NULL; } + virtual OuterStripMinedLoopEndNode* outer_loop_end() const { ShouldNotReachHere(); return NULL; } + virtual IfFalseNode* outer_loop_exit() const { ShouldNotReachHere(); return NULL; } + virtual SafePointNode* outer_safepoint() const { ShouldNotReachHere(); return NULL; } }; //------------------------------Counted Loops---------------------------------- @@ -278,6 +290,13 @@ public: void set_slp_max_unroll(int unroll_factor) { _slp_maximum_unroll_factor = unroll_factor; } int slp_max_unroll() const { return _slp_maximum_unroll_factor; } + virtual LoopNode* skip_strip_mined(int expect_opaq = 1); + OuterStripMinedLoopNode* outer_loop() const; + virtual IfTrueNode* outer_loop_tail() const; + virtual OuterStripMinedLoopEndNode* outer_loop_end() const; + virtual IfFalseNode* outer_loop_exit() const; + virtual SafePointNode* outer_safepoint() const; + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; #endif @@ -374,6 +393,40 @@ class LoopLimitNode : public Node { virtual Node* Identity(PhaseGVN* phase); }; +// Support for strip mining +class OuterStripMinedLoopNode : public LoopNode { +private: + CountedLoopNode* inner_loop() const; +public: + OuterStripMinedLoopNode(Compile* C, Node *entry, Node *backedge) + : LoopNode(entry, backedge) { + init_class_id(Class_OuterStripMinedLoop); + init_flags(Flag_is_macro); + C->add_macro_node(this); + } + + virtual int Opcode() const; + + virtual IfTrueNode* outer_loop_tail() const; + virtual OuterStripMinedLoopEndNode* outer_loop_end() const; + virtual IfFalseNode* outer_loop_exit() const; + virtual SafePointNode* outer_safepoint() const; + void adjust_strip_mined_loop(PhaseIterGVN* igvn); +}; + +class OuterStripMinedLoopEndNode : public IfNode { +public: + OuterStripMinedLoopEndNode(Node *control, Node *test, float prob, float cnt) + : IfNode(control, test, prob, cnt) { + init_class_id(Class_OuterStripMinedLoopEnd); + } + + virtual int Opcode() const; + + virtual const Type* Value(PhaseGVN* phase) const; + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); +}; + // -----------------------------IdealLoopTree---------------------------------- class IdealLoopTree : public ResourceObj { public: @@ -780,6 +833,7 @@ private: void build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ); void build_loop_late ( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ); void build_loop_late_post ( Node* n ); + void verify_strip_mined_scheduling(Node *n, Node* least); // Array of immediate dominance info for each CFG node indexed by node idx private: @@ -877,7 +931,10 @@ public: // Per-Node transform virtual Node *transform( Node *a_node ) { return 0; } - bool is_counted_loop( Node *x, IdealLoopTree *loop ); + bool is_counted_loop(Node* x, IdealLoopTree*& loop); + IdealLoopTree* create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, + IdealLoopTree* loop, float cl_prob, float le_fcnt, + Node*& entry_control, Node*& iffalse); Node* exact_limit( IdealLoopTree *loop ); @@ -908,8 +965,24 @@ public: // When nonnull, the clone and original are side-by-side, both are // dominated by the passed in side_by_side_idom node. Used in // construction of unswitched loops. + enum CloneLoopMode { + IgnoreStripMined = 0, // Only clone inner strip mined loop + CloneIncludesStripMined = 1, // clone both inner and outer strip mined loops + ControlAroundStripMined = 2 // Only clone inner strip mined loop, + // result control flow branches + // either to inner clone or outer + // strip mined loop. + }; void clone_loop( IdealLoopTree *loop, Node_List &old_new, int dom_depth, - Node* side_by_side_idom = NULL); + CloneLoopMode mode, Node* side_by_side_idom = NULL); + void clone_loop_handle_data_uses(Node* old, Node_List &old_new, + IdealLoopTree* loop, IdealLoopTree* companion_loop, + Node_List*& split_if_set, Node_List*& split_bool_set, + Node_List*& split_cex_set, Node_List& worklist, + uint new_counter, CloneLoopMode mode); + void clone_outer_loop(LoopNode* head, CloneLoopMode mode, IdealLoopTree *loop, + IdealLoopTree* outer_loop, int dd, Node_List &old_new, + Node_List& extra_data_nodes); // If we got the effect of peeling, either by actually peeling or by // making a pre-loop which must execute at least once, we can remove @@ -1020,7 +1093,8 @@ public: // and inserting an if to select fast-slow versions. ProjNode* create_slow_version_of_loop(IdealLoopTree *loop, Node_List &old_new, - int opcode); + int opcode, + CloneLoopMode mode); // Clone a loop and return the clone head (clone_loop_head). // Added nodes include int(1), int(0) - disconnected, If, IfTrue, IfFalse, @@ -1098,7 +1172,7 @@ public: // "Nearly" because all Nodes have been cloned from the original in the loop, // but the fall-in edges to the Cmp are different. Clone bool/Cmp pairs // through the Phi recursively, and return a Bool. - BoolNode *clone_iff( PhiNode *phi, IdealLoopTree *loop ); + Node *clone_iff( PhiNode *phi, IdealLoopTree *loop ); CmpNode *clone_bool( PhiNode *phi, IdealLoopTree *loop ); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 45acc2fcae2..d6ddc5723fe 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -26,6 +26,7 @@ #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "opto/addnode.hpp" +#include "opto/callnode.hpp" #include "opto/castnode.hpp" #include "opto/connode.hpp" #include "opto/castnode.hpp" @@ -306,7 +307,12 @@ Node *PhaseIdealLoop::has_local_phi_input( Node *n ) { get_ctrl(m->in(2)) != n_ctrl && get_ctrl(m->in(3)) != n_ctrl) { // Move the AddP up to dominating point - set_ctrl_and_loop(m, find_non_split_ctrl(idom(n_ctrl))); + Node* c = find_non_split_ctrl(idom(n_ctrl)); + if (c->is_OuterStripMinedLoop()) { + c->as_Loop()->verify_strip_mined(1); + c = c->in(LoopNode::EntryControl); + } + set_ctrl_and_loop(m, c); continue; } return NULL; @@ -750,14 +756,13 @@ Node* PhaseIdealLoop::try_move_store_before_loop(Node* n, Node *n_ctrl) { if (ctrl_ok) { // move the Store _igvn.replace_input_of(mem, LoopNode::LoopBackControl, mem); - _igvn.replace_input_of(n, 0, n_loop->_head->in(LoopNode::EntryControl)); + _igvn.replace_input_of(n, 0, n_loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl)); _igvn.replace_input_of(n, MemNode::Memory, mem->in(LoopNode::EntryControl)); // Disconnect the phi now. An empty phi can confuse other // optimizations in this pass of loop opts. _igvn.replace_node(mem, mem->in(LoopNode::EntryControl)); n_loop->_body.yank(mem); - IdealLoopTree* new_loop = get_loop(n->in(0)); set_ctrl_and_loop(n, n->in(0)); return n; @@ -840,6 +845,16 @@ void PhaseIdealLoop::try_move_store_after_loop(Node* n) { _igvn.replace_node(hook, n); return; } +#ifdef ASSERT + if (n_loop->_head->is_Loop() && n_loop->_head->as_Loop()->is_strip_mined()) { + assert(n_loop->_head->Opcode() == Op_CountedLoop, "outer loop is a strip mined"); + n_loop->_head->as_Loop()->verify_strip_mined(1); + Node* outer = n_loop->_head->as_CountedLoop()->outer_loop(); + IdealLoopTree* outer_loop = get_loop(outer); + assert(n_loop->_parent == outer_loop, "broken loop tree"); + assert(get_loop(lca) == outer_loop, "safepoint in outer loop consume all memory state"); + } +#endif // Move store out of the loop _igvn.replace_node(hook, n->in(MemNode::Memory)); @@ -1016,7 +1031,7 @@ Node *PhaseIdealLoop::place_near_use( Node *useblock ) const { IdealLoopTree *u_loop = get_loop( useblock ); return (u_loop->_irreducible || u_loop->_child) ? useblock - : u_loop->_head->in(LoopNode::EntryControl); + : u_loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl); } @@ -1407,47 +1422,56 @@ void PhaseIdealLoop::split_if_with_blocks( VectorSet &visited, Node_Stack &nstac // "Nearly" because all Nodes have been cloned from the original in the loop, // but the fall-in edges to the Cmp are different. Clone bool/Cmp pairs // through the Phi recursively, and return a Bool. -BoolNode *PhaseIdealLoop::clone_iff( PhiNode *phi, IdealLoopTree *loop ) { +Node* PhaseIdealLoop::clone_iff(PhiNode *phi, IdealLoopTree *loop) { // Convert this Phi into a Phi merging Bools uint i; - for( i = 1; i < phi->req(); i++ ) { + for (i = 1; i < phi->req(); i++) { Node *b = phi->in(i); - if( b->is_Phi() ) { - _igvn.replace_input_of(phi, i, clone_iff( b->as_Phi(), loop )); + if (b->is_Phi()) { + _igvn.replace_input_of(phi, i, clone_iff(b->as_Phi(), loop)); } else { - assert( b->is_Bool(), "" ); + assert(b->is_Bool() || b->Opcode() == Op_Opaque4, ""); } } - Node *sample_bool = phi->in(1); - Node *sample_cmp = sample_bool->in(1); + Node* n = phi->in(1); + Node* sample_opaque = NULL; + Node *sample_bool = NULL; + if (n->Opcode() == Op_Opaque4) { + sample_opaque = n; + sample_bool = n->in(1); + assert(sample_bool->is_Bool(), "wrong type"); + } else { + sample_bool = n; + } + Node *sample_cmp = sample_bool->in(1); // Make Phis to merge the Cmp's inputs. - PhiNode *phi1 = new PhiNode( phi->in(0), Type::TOP ); - PhiNode *phi2 = new PhiNode( phi->in(0), Type::TOP ); - for( i = 1; i < phi->req(); i++ ) { - Node *n1 = phi->in(i)->in(1)->in(1); - Node *n2 = phi->in(i)->in(1)->in(2); - phi1->set_req( i, n1 ); - phi2->set_req( i, n2 ); - phi1->set_type( phi1->type()->meet_speculative(n1->bottom_type())); - phi2->set_type( phi2->type()->meet_speculative(n2->bottom_type())); + PhiNode *phi1 = new PhiNode(phi->in(0), Type::TOP); + PhiNode *phi2 = new PhiNode(phi->in(0), Type::TOP); + for (i = 1; i < phi->req(); i++) { + Node *n1 = sample_opaque == NULL ? phi->in(i)->in(1)->in(1) : phi->in(i)->in(1)->in(1)->in(1); + Node *n2 = sample_opaque == NULL ? phi->in(i)->in(1)->in(2) : phi->in(i)->in(1)->in(1)->in(2); + phi1->set_req(i, n1); + phi2->set_req(i, n2); + phi1->set_type(phi1->type()->meet_speculative(n1->bottom_type())); + phi2->set_type(phi2->type()->meet_speculative(n2->bottom_type())); } // See if these Phis have been made before. // Register with optimizer Node *hit1 = _igvn.hash_find_insert(phi1); - if( hit1 ) { // Hit, toss just made Phi + if (hit1) { // Hit, toss just made Phi _igvn.remove_dead_node(phi1); // Remove new phi - assert( hit1->is_Phi(), "" ); + assert(hit1->is_Phi(), "" ); phi1 = (PhiNode*)hit1; // Use existing phi } else { // Miss _igvn.register_new_node_with_optimizer(phi1); } Node *hit2 = _igvn.hash_find_insert(phi2); - if( hit2 ) { // Hit, toss just made Phi + if (hit2) { // Hit, toss just made Phi _igvn.remove_dead_node(phi2); // Remove new phi - assert( hit2->is_Phi(), "" ); + assert(hit2->is_Phi(), "" ); phi2 = (PhiNode*)hit2; // Use existing phi } else { // Miss _igvn.register_new_node_with_optimizer(phi2); @@ -1457,8 +1481,8 @@ BoolNode *PhaseIdealLoop::clone_iff( PhiNode *phi, IdealLoopTree *loop ) { set_ctrl(phi2, phi->in(0)); // Make a new Cmp Node *cmp = sample_cmp->clone(); - cmp->set_req( 1, phi1 ); - cmp->set_req( 2, phi2 ); + cmp->set_req(1, phi1); + cmp->set_req(2, phi2); _igvn.register_new_node_with_optimizer(cmp); set_ctrl(cmp, phi->in(0)); @@ -1468,8 +1492,16 @@ BoolNode *PhaseIdealLoop::clone_iff( PhiNode *phi, IdealLoopTree *loop ) { _igvn.register_new_node_with_optimizer(b); set_ctrl(b, phi->in(0)); - assert( b->is_Bool(), "" ); - return (BoolNode*)b; + if (sample_opaque != NULL) { + Node* opaque = sample_opaque->clone(); + opaque->set_req(1, b); + _igvn.register_new_node_with_optimizer(opaque); + set_ctrl(opaque, phi->in(0)); + return opaque; + } + + assert(b->is_Bool(), ""); + return b; } //------------------------------clone_bool------------------------------------- @@ -1552,6 +1584,252 @@ void PhaseIdealLoop::sink_use( Node *use, Node *post_loop ) { } } +void PhaseIdealLoop::clone_loop_handle_data_uses(Node* old, Node_List &old_new, + IdealLoopTree* loop, IdealLoopTree* outer_loop, + Node_List*& split_if_set, Node_List*& split_bool_set, + Node_List*& split_cex_set, Node_List& worklist, + uint new_counter, CloneLoopMode mode) { + Node* nnn = old_new[old->_idx]; + // Copy uses to a worklist, so I can munge the def-use info + // with impunity. + for (DUIterator_Fast jmax, j = old->fast_outs(jmax); j < jmax; j++) + worklist.push(old->fast_out(j)); + + while( worklist.size() ) { + Node *use = worklist.pop(); + if (!has_node(use)) continue; // Ignore dead nodes + if (use->in(0) == C->top()) continue; + IdealLoopTree *use_loop = get_loop( has_ctrl(use) ? get_ctrl(use) : use ); + // Check for data-use outside of loop - at least one of OLD or USE + // must not be a CFG node. +#ifdef ASSERT + if (loop->_head->as_Loop()->is_strip_mined() && outer_loop->is_member(use_loop) && !loop->is_member(use_loop) && old_new[use->_idx] == NULL) { + Node* sfpt = loop->_head->as_CountedLoop()->outer_safepoint(); + assert(mode == ControlAroundStripMined && use == sfpt, "missed a node"); + } +#endif + if (!loop->is_member(use_loop) && !outer_loop->is_member(use_loop) && (!old->is_CFG() || !use->is_CFG())) { + + // If the Data use is an IF, that means we have an IF outside of the + // loop that is switching on a condition that is set inside of the + // loop. Happens if people set a loop-exit flag; then test the flag + // in the loop to break the loop, then test is again outside of the + // loop to determine which way the loop exited. + // Loop predicate If node connects to Bool node through Opaque1 node. + if (use->is_If() || use->is_CMove() || C->is_predicate_opaq(use) || use->Opcode() == Op_Opaque4) { + // Since this code is highly unlikely, we lazily build the worklist + // of such Nodes to go split. + if (!split_if_set) { + ResourceArea *area = Thread::current()->resource_area(); + split_if_set = new Node_List(area); + } + split_if_set->push(use); + } + if (use->is_Bool()) { + if (!split_bool_set) { + ResourceArea *area = Thread::current()->resource_area(); + split_bool_set = new Node_List(area); + } + split_bool_set->push(use); + } + if (use->Opcode() == Op_CreateEx) { + if (!split_cex_set) { + ResourceArea *area = Thread::current()->resource_area(); + split_cex_set = new Node_List(area); + } + split_cex_set->push(use); + } + + + // Get "block" use is in + uint idx = 0; + while( use->in(idx) != old ) idx++; + Node *prev = use->is_CFG() ? use : get_ctrl(use); + assert(!loop->is_member(get_loop(prev)) && !outer_loop->is_member(get_loop(prev)), "" ); + Node *cfg = prev->_idx >= new_counter + ? prev->in(2) + : idom(prev); + if( use->is_Phi() ) // Phi use is in prior block + cfg = prev->in(idx); // NOT in block of Phi itself + if (cfg->is_top()) { // Use is dead? + _igvn.replace_input_of(use, idx, C->top()); + continue; + } + + while(!outer_loop->is_member(get_loop(cfg))) { + prev = cfg; + cfg = cfg->_idx >= new_counter ? cfg->in(2) : idom(cfg); + } + // If the use occurs after merging several exits from the loop, then + // old value must have dominated all those exits. Since the same old + // value was used on all those exits we did not need a Phi at this + // merge point. NOW we do need a Phi here. Each loop exit value + // is now merged with the peeled body exit; each exit gets its own + // private Phi and those Phis need to be merged here. + Node *phi; + if( prev->is_Region() ) { + if( idx == 0 ) { // Updating control edge? + phi = prev; // Just use existing control + } else { // Else need a new Phi + phi = PhiNode::make( prev, old ); + // Now recursively fix up the new uses of old! + for( uint i = 1; i < prev->req(); i++ ) { + worklist.push(phi); // Onto worklist once for each 'old' input + } + } + } else { + // Get new RegionNode merging old and new loop exits + prev = old_new[prev->_idx]; + assert( prev, "just made this in step 7" ); + if( idx == 0) { // Updating control edge? + phi = prev; // Just use existing control + } else { // Else need a new Phi + // Make a new Phi merging data values properly + phi = PhiNode::make( prev, old ); + phi->set_req( 1, nnn ); + } + } + // If inserting a new Phi, check for prior hits + if( idx != 0 ) { + Node *hit = _igvn.hash_find_insert(phi); + if( hit == NULL ) { + _igvn.register_new_node_with_optimizer(phi); // Register new phi + } else { // or + // Remove the new phi from the graph and use the hit + _igvn.remove_dead_node(phi); + phi = hit; // Use existing phi + } + set_ctrl(phi, prev); + } + // Make 'use' use the Phi instead of the old loop body exit value + _igvn.replace_input_of(use, idx, phi); + if( use->_idx >= new_counter ) { // If updating new phis + // Not needed for correctness, but prevents a weak assert + // in AddPNode from tripping (when we end up with different + // base & derived Phis that will become the same after + // IGVN does CSE). + Node *hit = _igvn.hash_find_insert(use); + if( hit ) // Go ahead and re-hash for hits. + _igvn.replace_node( use, hit ); + } + + // If 'use' was in the loop-exit block, it now needs to be sunk + // below the post-loop merge point. + sink_use( use, prev ); + } + } +} + +void PhaseIdealLoop::clone_outer_loop(LoopNode* head, CloneLoopMode mode, IdealLoopTree *loop, + IdealLoopTree* outer_loop, int dd, Node_List &old_new, + Node_List& extra_data_nodes) { + if (head->is_strip_mined() && mode != IgnoreStripMined) { + CountedLoopNode* cl = head->as_CountedLoop(); + Node* l = cl->outer_loop(); + Node* tail = cl->outer_loop_tail(); + IfNode* le = cl->outer_loop_end(); + Node* sfpt = cl->outer_safepoint(); + CountedLoopEndNode* cle = cl->loopexit(); + CountedLoopNode* new_cl = old_new[cl->_idx]->as_CountedLoop(); + CountedLoopEndNode* new_cle = new_cl->as_CountedLoop()->loopexit(); + Node* cle_out = cle->proj_out(false); + + Node* new_sfpt = NULL; + Node* new_cle_out = cle_out->clone(); + old_new.map(cle_out->_idx, new_cle_out); + if (mode == CloneIncludesStripMined) { + // clone outer loop body + Node* new_l = l->clone(); + Node* new_tail = tail->clone(); + IfNode* new_le = le->clone()->as_If(); + new_sfpt = sfpt->clone(); + + set_loop(new_l, outer_loop->_parent); + set_idom(new_l, new_l->in(LoopNode::EntryControl), dd); + set_loop(new_cle_out, outer_loop->_parent); + set_idom(new_cle_out, new_cle, dd); + set_loop(new_sfpt, outer_loop->_parent); + set_idom(new_sfpt, new_cle_out, dd); + set_loop(new_le, outer_loop->_parent); + set_idom(new_le, new_sfpt, dd); + set_loop(new_tail, outer_loop->_parent); + set_idom(new_tail, new_le, dd); + set_idom(new_cl, new_l, dd); + + old_new.map(l->_idx, new_l); + old_new.map(tail->_idx, new_tail); + old_new.map(le->_idx, new_le); + old_new.map(sfpt->_idx, new_sfpt); + + new_l->set_req(LoopNode::LoopBackControl, new_tail); + new_l->set_req(0, new_l); + new_tail->set_req(0, new_le); + new_le->set_req(0, new_sfpt); + new_sfpt->set_req(0, new_cle_out); + new_cle_out->set_req(0, new_cle); + new_cl->set_req(LoopNode::EntryControl, new_l); + + _igvn.register_new_node_with_optimizer(new_l); + _igvn.register_new_node_with_optimizer(new_tail); + _igvn.register_new_node_with_optimizer(new_le); + } else { + Node *newhead = old_new[loop->_head->_idx]; + newhead->as_Loop()->clear_strip_mined(); + _igvn.replace_input_of(newhead, LoopNode::EntryControl, newhead->in(LoopNode::EntryControl)->in(LoopNode::EntryControl)); + set_idom(newhead, newhead->in(LoopNode::EntryControl), dd); + } + // Look at data node that were assigned a control in the outer + // loop: they are kept in the outer loop by the safepoint so start + // from the safepoint node's inputs. + IdealLoopTree* outer_loop = get_loop(l); + Node_Stack stack(2); + stack.push(sfpt, 1); + uint new_counter = C->unique(); + while (stack.size() > 0) { + Node* n = stack.node(); + uint i = stack.index(); + while (i < n->req() && + (n->in(i) == NULL || + !has_ctrl(n->in(i)) || + get_loop(get_ctrl(n->in(i))) != outer_loop || + (old_new[n->in(i)->_idx] != NULL && old_new[n->in(i)->_idx]->_idx >= new_counter))) { + i++; + } + if (i < n->req()) { + stack.set_index(i+1); + stack.push(n->in(i), 0); + } else { + assert(old_new[n->_idx] == NULL || n == sfpt || old_new[n->_idx]->_idx < new_counter, "no clone yet"); + Node* m = n == sfpt ? new_sfpt : n->clone(); + if (m != NULL) { + for (uint i = 0; i < n->req(); i++) { + if (m->in(i) != NULL && old_new[m->in(i)->_idx] != NULL) { + m->set_req(i, old_new[m->in(i)->_idx]); + } + } + } else { + assert(n == sfpt && mode != CloneIncludesStripMined, "where's the safepoint clone?"); + } + if (n != sfpt) { + extra_data_nodes.push(n); + _igvn.register_new_node_with_optimizer(m); + assert(get_ctrl(n) == cle_out, "what other control?"); + set_ctrl(m, new_cle_out); + old_new.map(n->_idx, m); + } + stack.pop(); + } + } + if (mode == CloneIncludesStripMined) { + _igvn.register_new_node_with_optimizer(new_sfpt); + _igvn.register_new_node_with_optimizer(new_cle_out); + } + } else { + Node *newhead = old_new[loop->_head->_idx]; + set_idom(newhead, newhead->in(LoopNode::EntryControl), dd); + } +} + //------------------------------clone_loop------------------------------------- // // C L O N E A L O O P B O D Y @@ -1580,7 +1858,10 @@ void PhaseIdealLoop::sink_use( Node *use, Node *post_loop ) { // dominated by the side_by_side_idom node. Used in construction of // unswitched loops. void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd, - Node* side_by_side_idom) { + CloneLoopMode mode, Node* side_by_side_idom) { + + LoopNode* head = loop->_head->as_Loop(); + head->verify_strip_mined(1); if (C->do_vector_loop() && PrintOpto) { const char* mname = C->method()->name()->as_quoted_ascii(); @@ -1613,6 +1894,7 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd _igvn.register_new_node_with_optimizer(nnn); } + IdealLoopTree* outer_loop = (head->is_strip_mined() && mode != IgnoreStripMined) ? get_loop(head->as_CountedLoop()->outer_loop()) : loop; // Step 2: Fix the edges in the new body. If the old input is outside the // loop use it. If the old input is INside the loop, use the corresponding @@ -1624,7 +1906,7 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd if (has_ctrl(old)) { set_ctrl(nnn, old_new[get_ctrl(old)->_idx]); } else { - set_loop(nnn, loop->_parent); + set_loop(nnn, outer_loop->_parent); if (old->outcnt() > 0) { set_idom( nnn, old_new[idom(old)->_idx], dd ); } @@ -1640,22 +1922,21 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd } _igvn.hash_find_insert(nnn); } - Node *newhead = old_new[loop->_head->_idx]; - set_idom(newhead, newhead->in(LoopNode::EntryControl), dd); + ResourceArea *area = Thread::current()->resource_area(); + Node_List extra_data_nodes(area); + clone_outer_loop(head, mode, loop, outer_loop, dd, old_new, extra_data_nodes); // Step 3: Now fix control uses. Loop varying control uses have already // been fixed up (as part of all input edges in Step 2). Loop invariant // control uses must be either an IfFalse or an IfTrue. Make a merge // point to merge the old and new IfFalse/IfTrue nodes; make the use // refer to this. - ResourceArea *area = Thread::current()->resource_area(); Node_List worklist(area); uint new_counter = C->unique(); for( i = 0; i < loop->_body.size(); i++ ) { Node* old = loop->_body.at(i); if( !old->is_CFG() ) continue; - Node* nnn = old_new[old->_idx]; // Copy uses to a worklist, so I can munge the def-use info // with impunity. @@ -1669,9 +1950,29 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd if( !loop->is_member( use_loop ) && use->is_CFG() ) { // Both OLD and USE are CFG nodes here. assert( use->is_Proj(), "" ); + Node* nnn = old_new[old->_idx]; + + Node* newuse = NULL; + if (head->is_strip_mined() && mode != IgnoreStripMined) { + CountedLoopNode* cl = head->as_CountedLoop(); + CountedLoopEndNode* cle = cl->loopexit(); + Node* cle_out = cle->proj_out(false); + if (use == cle_out) { + IfNode* le = cl->outer_loop_end(); + use = le->proj_out(false); + use_loop = get_loop(use); + if (mode == CloneIncludesStripMined) { + nnn = old_new[le->_idx]; + } else { + newuse = old_new[cle_out->_idx]; + } + } + } + if (newuse == NULL) { + newuse = use->clone(); + } // Clone the loop exit control projection - Node *newuse = use->clone(); if (C->do_vector_loop()) { cm.verify_insert_and_clone(use, newuse, cm.clone_idx()); } @@ -1705,6 +2006,10 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd if( useuse->in(k) == use ) { useuse->set_req(k, r); uses_found++; + if (useuse->is_Loop() && k == LoopNode::EntryControl) { + assert(dom_depth(useuse) > dd_r , ""); + set_idom(useuse, r, dom_depth(useuse)); + } } } l -= uses_found; // we deleted 1 or more copies of this edge @@ -1728,123 +2033,16 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd Node_List *split_cex_set = NULL; for( i = 0; i < loop->_body.size(); i++ ) { Node* old = loop->_body.at(i); - Node* nnn = old_new[old->_idx]; - // Copy uses to a worklist, so I can munge the def-use info - // with impunity. - for (DUIterator_Fast jmax, j = old->fast_outs(jmax); j < jmax; j++) - worklist.push(old->fast_out(j)); + clone_loop_handle_data_uses(old, old_new, loop, outer_loop, split_if_set, + split_bool_set, split_cex_set, worklist, new_counter, + mode); + } - while( worklist.size() ) { - Node *use = worklist.pop(); - if (!has_node(use)) continue; // Ignore dead nodes - if (use->in(0) == C->top()) continue; - IdealLoopTree *use_loop = get_loop( has_ctrl(use) ? get_ctrl(use) : use ); - // Check for data-use outside of loop - at least one of OLD or USE - // must not be a CFG node. - if( !loop->is_member( use_loop ) && (!old->is_CFG() || !use->is_CFG())) { - - // If the Data use is an IF, that means we have an IF outside of the - // loop that is switching on a condition that is set inside of the - // loop. Happens if people set a loop-exit flag; then test the flag - // in the loop to break the loop, then test is again outside of the - // loop to determine which way the loop exited. - // Loop predicate If node connects to Bool node through Opaque1 node. - if (use->is_If() || use->is_CMove() || C->is_predicate_opaq(use)) { - // Since this code is highly unlikely, we lazily build the worklist - // of such Nodes to go split. - if( !split_if_set ) - split_if_set = new Node_List(area); - split_if_set->push(use); - } - if( use->is_Bool() ) { - if( !split_bool_set ) - split_bool_set = new Node_List(area); - split_bool_set->push(use); - } - if( use->Opcode() == Op_CreateEx ) { - if( !split_cex_set ) - split_cex_set = new Node_List(area); - split_cex_set->push(use); - } - - - // Get "block" use is in - uint idx = 0; - while( use->in(idx) != old ) idx++; - Node *prev = use->is_CFG() ? use : get_ctrl(use); - assert( !loop->is_member( get_loop( prev ) ), "" ); - Node *cfg = prev->_idx >= new_counter - ? prev->in(2) - : idom(prev); - if( use->is_Phi() ) // Phi use is in prior block - cfg = prev->in(idx); // NOT in block of Phi itself - if (cfg->is_top()) { // Use is dead? - _igvn.replace_input_of(use, idx, C->top()); - continue; - } - - while( !loop->is_member( get_loop( cfg ) ) ) { - prev = cfg; - cfg = cfg->_idx >= new_counter ? cfg->in(2) : idom(cfg); - } - // If the use occurs after merging several exits from the loop, then - // old value must have dominated all those exits. Since the same old - // value was used on all those exits we did not need a Phi at this - // merge point. NOW we do need a Phi here. Each loop exit value - // is now merged with the peeled body exit; each exit gets its own - // private Phi and those Phis need to be merged here. - Node *phi; - if( prev->is_Region() ) { - if( idx == 0 ) { // Updating control edge? - phi = prev; // Just use existing control - } else { // Else need a new Phi - phi = PhiNode::make( prev, old ); - // Now recursively fix up the new uses of old! - for( uint i = 1; i < prev->req(); i++ ) { - worklist.push(phi); // Onto worklist once for each 'old' input - } - } - } else { - // Get new RegionNode merging old and new loop exits - prev = old_new[prev->_idx]; - assert( prev, "just made this in step 7" ); - if( idx == 0 ) { // Updating control edge? - phi = prev; // Just use existing control - } else { // Else need a new Phi - // Make a new Phi merging data values properly - phi = PhiNode::make( prev, old ); - phi->set_req( 1, nnn ); - } - } - // If inserting a new Phi, check for prior hits - if( idx != 0 ) { - Node *hit = _igvn.hash_find_insert(phi); - if( hit == NULL ) { - _igvn.register_new_node_with_optimizer(phi); // Register new phi - } else { // or - // Remove the new phi from the graph and use the hit - _igvn.remove_dead_node(phi); - phi = hit; // Use existing phi - } - set_ctrl(phi, prev); - } - // Make 'use' use the Phi instead of the old loop body exit value - _igvn.replace_input_of(use, idx, phi); - if( use->_idx >= new_counter ) { // If updating new phis - // Not needed for correctness, but prevents a weak assert - // in AddPNode from tripping (when we end up with different - // base & derived Phis that will become the same after - // IGVN does CSE). - Node *hit = _igvn.hash_find_insert(use); - if( hit ) // Go ahead and re-hash for hits. - _igvn.replace_node( use, hit ); - } - - // If 'use' was in the loop-exit block, it now needs to be sunk - // below the post-loop merge point. - sink_use( use, prev ); - } - } + for (i = 0; i < extra_data_nodes.size(); i++) { + Node* old = extra_data_nodes.at(i); + clone_loop_handle_data_uses(old, old_new, loop, outer_loop, split_if_set, + split_bool_set, split_cex_set, worklist, new_counter, + mode); } // Check for IFs that need splitting/cloning. Happens if an IF outside of @@ -1852,31 +2050,31 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd // takes control from one or more OLD Regions (which in turn get from NEW // Regions). In any case, there will be a set of Phis for each merge point // from the IF up to where the original BOOL def exists the loop. - if( split_if_set ) { - while( split_if_set->size() ) { + if (split_if_set) { + while (split_if_set->size()) { Node *iff = split_if_set->pop(); - if( iff->in(1)->is_Phi() ) { - BoolNode *b = clone_iff( iff->in(1)->as_Phi(), loop ); + if (iff->in(1)->is_Phi()) { + Node *b = clone_iff(iff->in(1)->as_Phi(), loop); _igvn.replace_input_of(iff, 1, b); } } } - if( split_bool_set ) { - while( split_bool_set->size() ) { + if (split_bool_set) { + while (split_bool_set->size()) { Node *b = split_bool_set->pop(); Node *phi = b->in(1); - assert( phi->is_Phi(), "" ); - CmpNode *cmp = clone_bool( (PhiNode*)phi, loop ); + assert(phi->is_Phi(), ""); + CmpNode *cmp = clone_bool((PhiNode*)phi, loop); _igvn.replace_input_of(b, 1, cmp); } } - if( split_cex_set ) { - while( split_cex_set->size() ) { + if (split_cex_set) { + while (split_cex_set->size()) { Node *b = split_cex_set->pop(); - assert( b->in(0)->is_Region(), "" ); - assert( b->in(1)->is_Phi(), "" ); - assert( b->in(0)->in(0) == b->in(1)->in(0), "" ); - split_up( b, b->in(0), NULL ); + assert(b->in(0)->is_Region(), ""); + assert(b->in(1)->is_Phi(), ""); + assert(b->in(0)->in(0) == b->in(1)->in(0), ""); + split_up(b, b->in(0), NULL); } } @@ -2936,7 +3134,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) { assert(is_valid_loop_partition(loop, peel, peel_list, not_peel), "bad partition"); - clone_loop( loop, old_new, dd ); + clone_loop(loop, old_new, dd, IgnoreStripMined); const uint clone_exit_idx = 1; const uint orig_exit_idx = 2; diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index a6ec2ff4267..8e8737f65c6 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -282,7 +282,8 @@ void PhaseMacroExpand::eliminate_card_mark(Node* p2x) { if (!this_region->in(ind)->is_IfFalse()) { ind = 2; } - if (this_region->in(ind)->is_IfFalse()) { + if (this_region->in(ind)->is_IfFalse() && + this_region->in(ind)->in(0)->Opcode() == Op_If) { Node* bol = this_region->in(ind)->in(0)->in(1); assert(bol->is_Bool(), ""); cmpx = bol->in(1); @@ -2660,6 +2661,8 @@ void PhaseMacroExpand::eliminate_macro_nodes() { break; case Node::Class_ArrayCopy: break; + case Node::Class_OuterStripMinedLoop: + break; default: assert(n->Opcode() == Op_LoopLimit || n->Opcode() == Op_Opaque1 || @@ -2733,6 +2736,10 @@ bool PhaseMacroExpand::expand_macro_nodes() { } else if (n->Opcode() == Op_Opaque4) { _igvn.replace_node(n, n->in(2)); success = true; + } else if (n->Opcode() == Op_OuterStripMinedLoop) { + n->as_OuterStripMinedLoop()->adjust_strip_mined_loop(&_igvn); + C->remove_macro_node(n); + success = true; } assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); progress = progress || success; diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 658b54fd358..17942bac08b 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -111,6 +111,8 @@ class MulNode; class MultiNode; class MultiBranchNode; class NeverBranchNode; +class OuterStripMinedLoopNode; +class OuterStripMinedLoopEndNode; class Node; class Node_Array; class Node_List; @@ -623,8 +625,9 @@ public: DEFINE_CLASS_ID(Catch, PCTable, 0) DEFINE_CLASS_ID(Jump, PCTable, 1) DEFINE_CLASS_ID(If, MultiBranch, 1) - DEFINE_CLASS_ID(CountedLoopEnd, If, 0) - DEFINE_CLASS_ID(RangeCheck, If, 1) + DEFINE_CLASS_ID(CountedLoopEnd, If, 0) + DEFINE_CLASS_ID(RangeCheck, If, 1) + DEFINE_CLASS_ID(OuterStripMinedLoopEnd, If, 2) DEFINE_CLASS_ID(NeverBranch, MultiBranch, 2) DEFINE_CLASS_ID(Start, Multi, 2) DEFINE_CLASS_ID(MemBar, Multi, 3) @@ -684,8 +687,9 @@ public: DEFINE_CLASS_ID(Region, Node, 5) DEFINE_CLASS_ID(Loop, Region, 0) - DEFINE_CLASS_ID(Root, Loop, 0) - DEFINE_CLASS_ID(CountedLoop, Loop, 1) + DEFINE_CLASS_ID(Root, Loop, 0) + DEFINE_CLASS_ID(CountedLoop, Loop, 1) + DEFINE_CLASS_ID(OuterStripMinedLoop, Loop, 2) DEFINE_CLASS_ID(Sub, Node, 6) DEFINE_CLASS_ID(Cmp, Sub, 0) @@ -841,6 +845,8 @@ public: DEFINE_CLASS_QUERY(Mul) DEFINE_CLASS_QUERY(Multi) DEFINE_CLASS_QUERY(MultiBranch) + DEFINE_CLASS_QUERY(OuterStripMinedLoop) + DEFINE_CLASS_QUERY(OuterStripMinedLoopEnd) DEFINE_CLASS_QUERY(Parm) DEFINE_CLASS_QUERY(PCTable) DEFINE_CLASS_QUERY(Phi) diff --git a/src/hotspot/share/opto/reg_split.cpp b/src/hotspot/share/opto/reg_split.cpp index d0c72c3a5b1..05f42d5a343 100644 --- a/src/hotspot/share/opto/reg_split.cpp +++ b/src/hotspot/share/opto/reg_split.cpp @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "libadt/vectset.hpp" #include "memory/allocation.inline.hpp" -#include "memory/resourceArea.hpp" +#include "memory/resourceArea.inline.hpp" #include "opto/addnode.hpp" #include "opto/c2compiler.hpp" #include "opto/callnode.hpp" diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index 0634b5efb5e..c3a9965bdf3 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -169,7 +169,7 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { assert(u->in(1) == bol, ""); // Get control block of either the CMove or the If input Node *u_ctrl = u->is_If() ? u->in(0) : get_ctrl(u); - assert(u_ctrl != blk1 && u_ctrl != blk2, "won't converge"); + assert((u_ctrl != blk1 && u_ctrl != blk2) || u->is_CMove(), "won't converge"); Node *x = bol->clone(); register_new_node(x, u_ctrl); _igvn.replace_input_of(u, 1, x); diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index cc1d881f10d..f53c9eb14f8 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1595,3 +1595,12 @@ const Type* SqrtDNode::Value(PhaseGVN* phase) const { if( d < 0.0 ) return Type::DOUBLE; return TypeD::make( sqrt( d ) ); } + +const Type* SqrtFNode::Value(PhaseGVN* phase) const { + const Type *t1 = phase->type( in(1) ); + if( t1 == Type::TOP ) return Type::TOP; + if( t1->base() != Type::FloatCon ) return Type::FLOAT; + float f = t1->getf(); + if( f < 0.0f ) return Type::FLOAT; + return TypeF::make( (float)sqrt( (double)f ) ); +} diff --git a/src/hotspot/share/opto/subnode.hpp b/src/hotspot/share/opto/subnode.hpp index a4adbcf5a47..68aa1a3c0b8 100644 --- a/src/hotspot/share/opto/subnode.hpp +++ b/src/hotspot/share/opto/subnode.hpp @@ -442,6 +442,20 @@ public: virtual const Type* Value(PhaseGVN* phase) const; }; +//------------------------------SqrtFNode-------------------------------------- +// square root a float +class SqrtFNode : public Node { +public: + SqrtFNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } + virtual int Opcode() const; + const Type *bottom_type() const { return Type::FLOAT; } + virtual uint ideal_reg() const { return Op_RegF; } + virtual const Type* Value(PhaseGVN* phase) const; +}; + //-------------------------------ReverseBytesINode-------------------------------- // reverse bytes of an integer class ReverseBytesINode : public Node { diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index b0afe8e5c74..39a525a1955 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -1102,7 +1102,7 @@ bool SuperWord::stmts_can_pack(Node* s1, Node* s2, int align) { } if (isomorphic(s1, s2)) { - if (independent(s1, s2) || reduction(s1, s2)) { + if ((independent(s1, s2) && have_similar_inputs(s1, s2)) || reduction(s1, s2)) { if (!exists_at(s1, 0) && !exists_at(s2, 1)) { if (!s1->is_Mem() || are_adjacent_refs(s1, s2)) { int s1_align = alignment(s1); @@ -1180,6 +1180,20 @@ bool SuperWord::independent(Node* s1, Node* s2) { return independent_path(shallow, deep); } +//--------------------------have_similar_inputs----------------------- +// For a node pair (s1, s2) which is isomorphic and independent, +// do s1 and s2 have similar input edges? +bool SuperWord::have_similar_inputs(Node* s1, Node* s2) { + // assert(isomorphic(s1, s2) == true, "check isomorphic"); + // assert(independent(s1, s2) == true, "check independent"); + if (s1->req() > 1 && !s1->is_Store() && !s1->is_Load()) { + for (uint i = 1; i < s1->req(); i++) { + if (s1->in(i)->Opcode() != s2->in(i)->Opcode()) return false; + } + } + return true; +} + //------------------------------reduction--------------------------- // Is there a data path between s1 and s2 and the nodes reductions? bool SuperWord::reduction(Node* s1, Node* s2) { @@ -1339,6 +1353,7 @@ bool SuperWord::follow_def_uses(Node_List* p) { for (DUIterator_Fast jmax, j = s2->fast_outs(jmax); j < jmax; j++) { Node* t2 = s2->fast_out(j); if (!in_bb(t2)) continue; + if (t2->Opcode() == Op_AddI && t2 == _lp->as_CountedLoop()->incr()) continue; // don't mess with the iv if (!opnd_positions_match(s1, t1, s2, t2)) continue; if (stmts_can_pack(t1, t2, align)) { @@ -2307,7 +2322,7 @@ void SuperWord::output() { vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n)); vlen_in_bytes = vn->as_Vector()->length_in_bytes(); } - } else if (opc == Op_SqrtD || opc == Op_AbsF || opc == Op_AbsD || opc == Op_NegF || opc == Op_NegD) { + } else if (opc == Op_SqrtF || opc == Op_SqrtD || opc == Op_AbsF || opc == Op_AbsD || opc == Op_NegF || opc == Op_NegD) { // Promote operand to vector (Sqrt/Abs/Neg are 2 address instructions) Node* in = vector_opd(p, 1); vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n)); @@ -3299,7 +3314,7 @@ CountedLoopEndNode* SuperWord::get_pre_loop_end(CountedLoopNode* cl) { return NULL; } - Node* p_f = cl->in(LoopNode::EntryControl)->in(0)->in(0); + Node* p_f = cl->skip_strip_mined()->in(LoopNode::EntryControl)->in(0)->in(0); if (!p_f->is_IfFalse()) return NULL; if (!p_f->in(0)->is_CountedLoopEnd()) return NULL; CountedLoopEndNode* pre_end = p_f->in(0)->as_CountedLoopEnd(); diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 28a4f3c28de..8a4241afdf4 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -442,6 +442,9 @@ class SuperWord : public ResourceObj { bool isomorphic(Node* s1, Node* s2); // Is there no data path from s1 to s2 or s2 to s1? bool independent(Node* s1, Node* s2); + // For a node pair (s1, s2) which is isomorphic and independent, + // do s1 and s2 have similar input edges? + bool have_similar_inputs(Node* s1, Node* s2); // Is there a data path between s1 and s2 and both are reductions? bool reduction(Node* s1, Node* s2); // Helper for independent diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index ecf8247825e..57b0ecf0e7b 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -113,6 +113,9 @@ int VectorNode::opcode(int sopc, BasicType bt) { case Op_NegD: assert(bt == T_DOUBLE, "must be"); return Op_NegVD; + case Op_SqrtF: + assert(bt == T_FLOAT, "must be"); + return Op_SqrtVF; case Op_SqrtD: assert(bt == T_DOUBLE, "must be"); return Op_SqrtVD; @@ -316,7 +319,7 @@ VectorNode* VectorNode::make(int opc, Node* n1, Node* n2, uint vlen, BasicType b case Op_NegVF: return new NegVFNode(n1, vt); case Op_NegVD: return new NegVDNode(n1, vt); - // Currently only supports double precision sqrt + case Op_SqrtVF: return new SqrtVFNode(n1, vt); case Op_SqrtVD: return new SqrtVDNode(n1, vt); case Op_LShiftVB: return new LShiftVBNode(n1, n2, vt); diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 7b65aa9a91d..93da7bc4b7c 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -373,6 +373,14 @@ class NegVDNode : public VectorNode { virtual int Opcode() const; }; +//------------------------------SqrtVFNode-------------------------------------- +// Vector Sqrt float +class SqrtVFNode : public VectorNode { + public: + SqrtVFNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {} + virtual int Opcode() const; +}; + //------------------------------SqrtVDNode-------------------------------------- // Vector Sqrt double class SqrtVDNode : public VectorNode { diff --git a/src/hotspot/share/precompiled/precompiled.hpp b/src/hotspot/share/precompiled/precompiled.hpp index dd76a0b9c93..728a75535c0 100644 --- a/src/hotspot/share/precompiled/precompiled.hpp +++ b/src/hotspot/share/precompiled/precompiled.hpp @@ -131,7 +131,6 @@ # include "jvmtifiles/jvmti.h" # include "logging/log.hpp" # include "memory/allocation.hpp" -# include "memory/allocation.inline.hpp" # include "memory/arena.hpp" # include "memory/heap.hpp" # include "memory/iterator.hpp" diff --git a/src/hotspot/share/prims/cdsoffsets.cpp b/src/hotspot/share/prims/cdsoffsets.cpp new file mode 100644 index 00000000000..d38b7efbfff --- /dev/null +++ b/src/hotspot/share/prims/cdsoffsets.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 2017, 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 "utilities/macros.hpp" +#if INCLUDE_CDS +#include "runtime/os.hpp" +#include "memory/filemap.hpp" +#include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" +#include "prims/cdsoffsets.hpp" + +CDSOffsets* CDSOffsets::_all = NULL; +#define ADD_NEXT(list, name, value) \ + list->add_end(new CDSOffsets(name, value, NULL)) + +#define CREATE_OFFSET_MAPS \ + _all = new CDSOffsets("size_t_size", sizeof(size_t), NULL); \ + ADD_NEXT(_all, "FileMapHeader::_magic", offset_of(FileMapInfo::FileMapHeader, _magic)); \ + ADD_NEXT(_all, "FileMapHeader::_crc", offset_of(FileMapInfo::FileMapHeader, _crc)); \ + ADD_NEXT(_all, "FileMapHeader::_version", offset_of(FileMapInfo::FileMapHeader, _version)); \ + ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapInfo::FileMapHeader, _space)); \ + ADD_NEXT(_all, "space_info::_crc", offset_of(FileMapInfo::FileMapHeader::space_info, _crc)); \ + ADD_NEXT(_all, "space_info::_used", offset_of(FileMapInfo::FileMapHeader::space_info, _used)); \ + ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapInfo::FileMapHeader, _paths_misc_info_size)); \ + ADD_NEXT(_all, "file_header_size", sizeof(FileMapInfo::FileMapHeader)); \ + ADD_NEXT(_all, "space_info_size", sizeof(FileMapInfo::FileMapHeader::space_info)); + +int CDSOffsets::find_offset(const char* name) { + if (_all == NULL) { + CREATE_OFFSET_MAPS + } + CDSOffsets* it = _all; + while(it) { + if (!strcmp(name, it->get_name())) { + return it->get_offset(); + } + it = it->next(); + } + return -1; // not found +} + +void CDSOffsets::add_end(CDSOffsets* n) { + CDSOffsets* p = this; + while(p && p->_next) { p = p->_next; } + p->_next = n; +} +#endif // INCLUDE_CDS diff --git a/src/hotspot/share/prims/cdsoffsets.hpp b/src/hotspot/share/prims/cdsoffsets.hpp new file mode 100644 index 00000000000..aa147cc70a0 --- /dev/null +++ b/src/hotspot/share/prims/cdsoffsets.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 2017, 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_PRIMS_CDSOFFSETS_HPP +#define SHARE_PRIMS_CDSOFFSETS_HPP +class CDSOffsets: public CHeapObj { + private: + char* _name; + int _offset; + CDSOffsets* _next; + static CDSOffsets* _all; // sole list for cds + public: + CDSOffsets(const char* name, int offset, CDSOffsets* next) { + _name = NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal); + strcpy(_name, name); + _offset = offset; + _next = next; + } + + char* get_name() const { return _name; } + int get_offset() const { return _offset; } + CDSOffsets* next() const { return _next; } + void add_end(CDSOffsets* n); + + static int find_offset(const char* name); +}; +#endif // SHARE_PRIMS_CDSOFFSETS_HPP diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index 26aedaaebe5..06d0f91a6b1 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -4119,7 +4119,7 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae thread->initialize_thread_current(); if (!os::create_attached_thread(thread)) { - delete thread; + thread->smr_delete(); return JNI_ERR; } // Enable stack overflow checks @@ -4250,7 +4250,7 @@ jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { // (platform-dependent) methods where we do alternate stack // maintenance work?) thread->exit(false, JavaThread::jni_detach); - delete thread; + thread->smr_delete(); HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK); return JNI_OK; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 368696e5d08..ad3a1cedb46 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -66,6 +66,7 @@ #include "runtime/perfData.hpp" #include "runtime/reflection.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vm_operations.hpp" #include "runtime/vm_version.hpp" @@ -2737,16 +2738,12 @@ void jio_print(const char* s) { // java.lang.Thread ////////////////////////////////////////////////////////////////////////////// -// In most of the JVM Thread support functions we need to be sure to lock the Threads_lock -// to prevent the target thread from exiting after we have a pointer to the C++ Thread or -// OSThread objects. The exception to this rule is when the target object is the thread -// doing the operation, in which case we know that the thread won't exit until the -// operation is done (all exits being voluntary). There are a few cases where it is -// rather silly to do operations on yourself, like resuming yourself or asking whether -// you are alive. While these can still happen, they are not subject to deadlocks if -// the lock is held while the operation occurs (this is not the case for suspend, for -// instance), and are very unlikely. Because IsAlive needs to be fast and its -// implementation is local to this file, we always lock Threads_lock for that one. +// In most of the JVM thread support functions we need to access the +// thread through a ThreadsListHandle to prevent it from exiting and +// being reclaimed while we try to operate on it. The exceptions to this +// rule are when operating on the current thread, or if the monitor of +// the target java.lang.Thread is locked at the Java level - in both +// cases the target cannot exit. static void thread_entry(JavaThread* thread, TRAPS) { HandleMark hm(THREAD); @@ -2821,7 +2818,7 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) if (native_thread->osthread() == NULL) { // No one should hold a reference to the 'native_thread'. - delete native_thread; + native_thread->smr_delete(); if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, @@ -2835,41 +2832,45 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) JVM_END + // JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints // before the quasi-asynchronous exception is delivered. This is a little obtrusive, // but is thought to be reliable and simple. In the case, where the receiver is the -// same thread as the sender, no safepoint is needed. +// same thread as the sender, no VM_Operation is needed. JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)) JVMWrapper("JVM_StopThread"); + // A nested ThreadsListHandle will grab the Threads_lock so create + // tlh before we resolve throwable. + ThreadsListHandle tlh(thread); oop java_throwable = JNIHandles::resolve(throwable); if (java_throwable == NULL) { THROW(vmSymbols::java_lang_NullPointerException()); } - oop java_thread = JNIHandles::resolve_non_null(jthread); - JavaThread* receiver = java_lang_Thread::thread(java_thread); - Events::log_exception(JavaThread::current(), + oop java_thread = NULL; + JavaThread* receiver = NULL; + bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, &java_thread); + Events::log_exception(thread, "JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", p2i(receiver), p2i((address)java_thread), p2i(throwable)); - // First check if thread is alive - if (receiver != NULL) { - // Check if exception is getting thrown at self (use oop equality, since the - // target object might exit) - if (java_thread == thread->threadObj()) { + + if (is_alive) { + // jthread refers to a live JavaThread. + if (thread == receiver) { + // Exception is getting thrown at self so no VM_Operation needed. THROW_OOP(java_throwable); } else { - // Enques a VM_Operation to stop all threads and then deliver the exception... - Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable)); + // Use a VM_Operation to throw the exception. + Thread::send_async_exception(java_thread, java_throwable); } - } - else { + } else { // Either: // - target thread has not been started before being stopped, or // - target thread already terminated // We could read the threadStatus to determine which case it is // but that is overkill as it doesn't matter. We must set the // stillborn flag for the first case, and if the thread has already - // exited setting this flag has no affect + // exited setting this flag has no effect. java_lang_Thread::set_stillborn(java_thread); } JVM_END @@ -2885,12 +2886,12 @@ JVM_END JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_SuspendThread"); - oop java_thread = JNIHandles::resolve_non_null(jthread); - JavaThread* receiver = java_lang_Thread::thread(java_thread); - - if (receiver != NULL) { - // thread has run and has not exited (still on threads list) + ThreadsListHandle tlh(thread); + JavaThread* receiver = NULL; + bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); + if (is_alive) { + // jthread refers to a live JavaThread. { MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag); if (receiver->is_external_suspend()) { @@ -2922,30 +2923,49 @@ JVM_END JVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_ResumeThread"); - // Ensure that the C++ Thread and OSThread structures aren't freed before we operate. - // We need to *always* get the threads lock here, since this operation cannot be allowed during - // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other - // threads randomly resumes threads, then a thread might not be suspended when the safepoint code - // looks at it. - MutexLocker ml(Threads_lock); - JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); - if (thr != NULL) { - // the thread has run and is not in the process of exiting - thr->java_resume(); + + ThreadsListHandle tlh(thread); + JavaThread* receiver = NULL; + bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); + if (is_alive) { + // jthread refers to a live JavaThread. + + // This is the original comment for this Threads_lock grab: + // We need to *always* get the threads lock here, since this operation cannot be allowed during + // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other + // threads randomly resumes threads, then a thread might not be suspended when the safepoint code + // looks at it. + // + // The above comment dates back to when we had both internal and + // external suspend APIs that shared a common underlying mechanism. + // External suspend is now entirely cooperative and doesn't share + // anything with internal suspend. That said, there are some + // assumptions in the VM that an external resume grabs the + // Threads_lock. We can't drop the Threads_lock grab here until we + // resolve the assumptions that exist elsewhere. + // + MutexLocker ml(Threads_lock); + receiver->java_resume(); } JVM_END JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)) JVMWrapper("JVM_SetThreadPriority"); - // Ensure that the C++ Thread and OSThread structures aren't freed before we operate - MutexLocker ml(Threads_lock); - oop java_thread = JNIHandles::resolve_non_null(jthread); + + ThreadsListHandle tlh(thread); + oop java_thread = NULL; + JavaThread* receiver = NULL; + bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, &java_thread); java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio); - JavaThread* thr = java_lang_Thread::thread(java_thread); - if (thr != NULL) { // Thread not yet started; priority pushed down when it is - Thread::set_priority(thr, (ThreadPriority)prio); + + if (is_alive) { + // jthread refers to a live JavaThread. + Thread::set_priority(receiver, (ThreadPriority)prio); } + // Implied else: If the JavaThread hasn't started yet, then the + // priority set in the java.lang.Thread object above will be pushed + // down when it does start. JVM_END @@ -3016,67 +3036,39 @@ JVM_END JVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_CountStackFrames"); - // Ensure that the C++ Thread and OSThread structures aren't freed before we operate - oop java_thread = JNIHandles::resolve_non_null(jthread); - bool throw_illegal_thread_state = false; + uint32_t debug_bits = 0; + ThreadsListHandle tlh(thread); + JavaThread* receiver = NULL; + bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); int count = 0; - - { - MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); - // We need to re-resolve the java_thread, since a GC might have happened during the - // acquire of the lock - JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); - - if (thr == NULL) { - // do nothing - } else if(! thr->is_external_suspend() || ! thr->frame_anchor()->walkable()) { - // Check whether this java thread has been suspended already. If not, throws - // IllegalThreadStateException. We defer to throw that exception until - // Threads_lock is released since loading exception class has to leave VM. - // The correct way to test a thread is actually suspended is - // wait_for_ext_suspend_completion(), but we can't call that while holding - // the Threads_lock. The above tests are sufficient for our purposes - // provided the walkability of the stack is stable - which it isn't - // 100% but close enough for most practical purposes. - throw_illegal_thread_state = true; - } else { - // Count all java activation, i.e., number of vframes - for(vframeStream vfst(thr); !vfst.at_end(); vfst.next()) { - // Native frames are not counted + if (is_alive) { + // jthread refers to a live JavaThread. + if (receiver->is_thread_fully_suspended(true /* wait for suspend completion */, &debug_bits)) { + // Count all java activation, i.e., number of vframes. + for (vframeStream vfst(receiver); !vfst.at_end(); vfst.next()) { + // Native frames are not counted. if (!vfst.method()->is_native()) count++; - } + } + } else { + THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(), + "this thread is not suspended"); } } + // Implied else: if JavaThread is not alive simply return a count of 0. - if (throw_illegal_thread_state) { - THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(), - "this thread is not suspended"); - } return count; JVM_END -// Consider: A better way to implement JVM_Interrupt() is to acquire -// Threads_lock to resolve the jthread into a Thread pointer, fetch -// Thread->platformevent, Thread->native_thr, Thread->parker, etc., -// drop Threads_lock, and the perform the unpark() and thr_kill() operations -// outside the critical section. Threads_lock is hot so we want to minimize -// the hold-time. A cleaner interface would be to decompose interrupt into -// two steps. The 1st phase, performed under Threads_lock, would return -// a closure that'd be invoked after Threads_lock was dropped. -// This tactic is safe as PlatformEvent and Parkers are type-stable (TSM) and -// admit spurious wakeups. JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_Interrupt"); - // Ensure that the C++ Thread and OSThread structures aren't freed before we operate - oop java_thread = JNIHandles::resolve_non_null(jthread); - MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); - // We need to re-resolve the java_thread, since a GC might have happened during the - // acquire of the lock - JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); - if (thr != NULL) { - Thread::interrupt(thr); + ThreadsListHandle tlh(thread); + JavaThread* receiver = NULL; + bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); + if (is_alive) { + // jthread refers to a live JavaThread. + Thread::interrupt(receiver); } JVM_END @@ -3084,16 +3076,14 @@ JVM_END JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted)) JVMWrapper("JVM_IsInterrupted"); - // Ensure that the C++ Thread and OSThread structures aren't freed before we operate - oop java_thread = JNIHandles::resolve_non_null(jthread); - MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); - // We need to re-resolve the java_thread, since a GC might have happened during the - // acquire of the lock - JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); - if (thr == NULL) { - return JNI_FALSE; + ThreadsListHandle tlh(thread); + JavaThread* receiver = NULL; + bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); + if (is_alive) { + // jthread refers to a live JavaThread. + return (jboolean) Thread::is_interrupted(receiver, clear_interrupted != 0); } else { - return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0); + return JNI_FALSE; } JVM_END @@ -3122,14 +3112,16 @@ JVM_END JVM_ENTRY(void, JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring name)) JVMWrapper("JVM_SetNativeThreadName"); - ResourceMark rm(THREAD); + + // We don't use a ThreadsListHandle here because the current thread + // must be alive. oop java_thread = JNIHandles::resolve_non_null(jthread); JavaThread* thr = java_lang_Thread::thread(java_thread); - // Thread naming only supported for the current thread, doesn't work for - // target threads. - if (Thread::current() == thr && !thr->has_attached_via_jni()) { + if (thread == thr && !thr->has_attached_via_jni()) { + // Thread naming is only supported for the current thread and // we don't set the name of an attached thread to avoid stepping - // on other programs + // on other programs. + ResourceMark rm(thread); const char *thread_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name)); os::set_native_thread_name(thread_name); } @@ -3561,6 +3553,8 @@ JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobject thread_handle_array->append(h); } + // The JavaThread references in thread_handle_array are validated + // in VM_ThreadDump::doit(). Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, stacktraces()); diff --git a/src/hotspot/share/prims/jvmtiEnter.xsl b/src/hotspot/share/prims/jvmtiEnter.xsl index fbb8724c7ab..406ddc642c0 100644 --- a/src/hotspot/share/prims/jvmtiEnter.xsl +++ b/src/hotspot/share/prims/jvmtiEnter.xsl @@ -45,6 +45,7 @@ # include "prims/jvmtiEnter.hpp" # include "prims/jvmtiRawMonitor.hpp" # include "prims/jvmtiUtil.hpp" +# include "runtime/threadSMR.hpp" @@ -769,47 +770,27 @@ static jvmtiError JNICALL - oop thread_oop = JNIHandles::resolve_external_guard( + err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), - ); - if (thread_oop == NULL) { + , &java_thread, NULL); + if (err != JVMTI_ERROR_NONE) { - JVMTI_ERROR_INVALID_THREAD - - jthread resolved to NULL - jthread = " PTR_FORMAT " + err + - jthread did not convert to a JavaThread - jthread = " PTR_FORMAT " , p2i() } - if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { - - JVMTI_ERROR_INVALID_THREAD - - oop is not a thread - jthread = " PTR_FORMAT " - , p2i() - - - } - java_thread = java_lang_Thread::thread(thread_oop); - if (java_thread == NULL) { - - - - JVMTI_ERROR_THREAD_NOT_ALIVE - - - not a Java thread - jthread = " PTR_FORMAT " - , p2i() - - - } - - JavaThread* java_thread; + JavaThread* java_thread = NULL; + ThreadsListHandle tlh(this_thread); diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index b67e23f45ad..bff8274a3ea 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -62,6 +62,7 @@ #include "runtime/reflectionUtils.hpp" #include "runtime/signature.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/timerTrace.hpp" #include "runtime/vframe.hpp" #include "runtime/vmThread.hpp" @@ -162,7 +163,6 @@ JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) { *data_ptr = (state == NULL) ? NULL : state->env_thread_state(this)->get_agent_thread_local_storage_data(); } else { - // jvmti_GetThreadLocalStorage is "in native" and doesn't transition // the thread to _thread_in_vm. However, when the TLS for a thread // other than the current thread is required we need to transition @@ -172,17 +172,13 @@ JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) { VM_ENTRY_BASE(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread) debug_only(VMNativeEntryWrapper __vew;) - oop thread_oop = JNIHandles::resolve_external_guard(thread); - if (thread_oop == NULL) { - return JVMTI_ERROR_INVALID_THREAD; - } - if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { - return JVMTI_ERROR_INVALID_THREAD; - } - JavaThread* java_thread = java_lang_Thread::thread(thread_oop); - if (java_thread == NULL) { - return JVMTI_ERROR_THREAD_NOT_ALIVE; + JavaThread* java_thread = NULL; + ThreadsListHandle tlh(current_thread); + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, NULL); + if (err != JVMTI_ERROR_NONE) { + return err; } + JvmtiThreadState* state = java_thread->jvmti_thread_state(); *data_ptr = (state == NULL) ? NULL : state->env_thread_state(this)->get_agent_thread_local_storage_data(); @@ -518,42 +514,60 @@ JvmtiEnv::SetEventCallbacks(const jvmtiEventCallbacks* callbacks, jint size_of_c // event_thread - NULL is a valid value, must be checked jvmtiError JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread, ...) { - JavaThread* java_thread = NULL; - if (event_thread != NULL) { - oop thread_oop = JNIHandles::resolve_external_guard(event_thread); - if (thread_oop == NULL) { - return JVMTI_ERROR_INVALID_THREAD; + if (event_thread == NULL) { + // Can be called at Agent_OnLoad() time with event_thread == NULL + // when Thread::current() does not work yet so we cannot create a + // ThreadsListHandle that is common to both thread-specific and + // global code paths. + + // event_type must be valid + if (!JvmtiEventController::is_valid_event_type(event_type)) { + return JVMTI_ERROR_INVALID_EVENT_TYPE; } - if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { - return JVMTI_ERROR_INVALID_THREAD; + + bool enabled = (mode == JVMTI_ENABLE); + + // assure that needed capabilities are present + if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) { + return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; } - java_thread = java_lang_Thread::thread(thread_oop); - if (java_thread == NULL) { - return JVMTI_ERROR_THREAD_NOT_ALIVE; + + if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) { + record_class_file_load_hook_enabled(); } - } + JvmtiEventController::set_user_enabled(this, (JavaThread*) NULL, event_type, enabled); + } else { + // We have a specified event_thread. - // event_type must be valid - if (!JvmtiEventController::is_valid_event_type(event_type)) { - return JVMTI_ERROR_INVALID_EVENT_TYPE; - } + JavaThread* java_thread = NULL; + ThreadsListHandle tlh; + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), event_thread, &java_thread, NULL); + if (err != JVMTI_ERROR_NONE) { + return err; + } - // global events cannot be controlled at thread level. - if (java_thread != NULL && JvmtiEventController::is_global_event(event_type)) { - return JVMTI_ERROR_ILLEGAL_ARGUMENT; - } + // event_type must be valid + if (!JvmtiEventController::is_valid_event_type(event_type)) { + return JVMTI_ERROR_INVALID_EVENT_TYPE; + } - bool enabled = (mode == JVMTI_ENABLE); + // global events cannot be controlled at thread level. + if (JvmtiEventController::is_global_event(event_type)) { + return JVMTI_ERROR_ILLEGAL_ARGUMENT; + } - // assure that needed capabilities are present - if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) { - return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; - } + bool enabled = (mode == JVMTI_ENABLE); - if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) { - record_class_file_load_hook_enabled(); + // assure that needed capabilities are present + if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) { + return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; + } + + if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) { + record_class_file_load_hook_enabled(); + } + JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled); } - JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled); return JVMTI_ERROR_NONE; } /* end SetEventNotificationMode */ @@ -817,35 +831,45 @@ JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { // thread_state_ptr - pre-checked for NULL jvmtiError JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) { - jint state; - oop thread_oop; - JavaThread* thr; + JavaThread* current_thread = JavaThread::current(); + JavaThread* java_thread = NULL; + oop thread_oop = NULL; + ThreadsListHandle tlh(current_thread); if (thread == NULL) { - thread_oop = JavaThread::current()->threadObj(); - } else { - thread_oop = JNIHandles::resolve_external_guard(thread); - } + java_thread = current_thread; + thread_oop = java_thread->threadObj(); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { - return JVMTI_ERROR_INVALID_THREAD; + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { + return JVMTI_ERROR_INVALID_THREAD; + } + } else { + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, &thread_oop); + if (err != JVMTI_ERROR_NONE) { + // We got an error code so we don't have a JavaThread *, but + // only return an error from here if we didn't get a valid + // thread_oop. + if (thread_oop == NULL) { + return err; + } + // We have a valid thread_oop so we can return some thread state. + } } // get most state bits - state = (jint)java_lang_Thread::get_thread_status(thread_oop); + jint state = (jint)java_lang_Thread::get_thread_status(thread_oop); - // add more state bits - thr = java_lang_Thread::thread(thread_oop); - if (thr != NULL) { - JavaThreadState jts = thr->thread_state(); + if (java_thread != NULL) { + // We have a JavaThread* so add more state bits. + JavaThreadState jts = java_thread->thread_state(); - if (thr->is_being_ext_suspended()) { + if (java_thread->is_being_ext_suspended()) { state |= JVMTI_THREAD_STATE_SUSPENDED; } if (jts == _thread_in_native) { state |= JVMTI_THREAD_STATE_IN_NATIVE; } - OSThread* osThread = thr->osthread(); + OSThread* osThread = java_thread->osthread(); if (osThread != NULL && osThread->interrupted()) { state |= JVMTI_THREAD_STATE_INTERRUPTED; } @@ -891,7 +915,6 @@ JvmtiEnv::GetAllThreads(jint* threads_count_ptr, jthread** threads_ptr) { thread_objs[i] = Handle(tle.get_threadObj(i)); } - // have to make global handles outside of Threads_lock jthread *jthreads = new_jthreadArray(nthreads, thread_objs); NULL_CHECK(jthreads, JVMTI_ERROR_OUT_OF_MEMORY); @@ -935,19 +958,12 @@ JvmtiEnv::SuspendThread(JavaThread* java_thread) { jvmtiError JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { int needSafepoint = 0; // > 0 if we need a safepoint + ThreadsListHandle tlh; for (int i = 0; i < request_count; i++) { - JavaThread *java_thread = get_JavaThread(request_list[i]); - if (java_thread == NULL) { - results[i] = JVMTI_ERROR_INVALID_THREAD; - continue; - } - // the thread has not yet run or has exited (not on threads list) - if (java_thread->threadObj() == NULL) { - results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; - continue; - } - if (java_lang_Thread::thread(java_thread->threadObj()) == NULL) { - results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; + JavaThread *java_thread = NULL; + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), request_list[i], &java_thread, NULL); + if (err != JVMTI_ERROR_NONE) { + results[i] = err; continue; } // don't allow hidden thread suspend request. @@ -1018,10 +1034,12 @@ JvmtiEnv::ResumeThread(JavaThread* java_thread) { // results - pre-checked for NULL jvmtiError JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { + ThreadsListHandle tlh; for (int i = 0; i < request_count; i++) { - JavaThread *java_thread = get_JavaThread(request_list[i]); - if (java_thread == NULL) { - results[i] = JVMTI_ERROR_INVALID_THREAD; + JavaThread* java_thread = NULL; + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), request_list[i], &java_thread, NULL); + if (err != JVMTI_ERROR_NONE) { + results[i] = err; continue; } // don't allow hidden thread resume request. @@ -1039,7 +1057,7 @@ JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmt continue; } - results[i] = JVMTI_ERROR_NONE; // indicate successful suspend + results[i] = JVMTI_ERROR_NONE; // indicate successful resume } // per-thread resume results returned via results parameter return JVMTI_ERROR_NONE; @@ -1064,20 +1082,14 @@ JvmtiEnv::StopThread(JavaThread* java_thread, jobject exception) { // thread - NOT pre-checked jvmtiError JvmtiEnv::InterruptThread(jthread thread) { - oop thread_oop = JNIHandles::resolve_external_guard(thread); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) - return JVMTI_ERROR_INVALID_THREAD; - + // TODO: this is very similar to JVM_Interrupt(); share code in future JavaThread* current_thread = JavaThread::current(); - - // Todo: this is a duplicate of JVM_Interrupt; share code in future - // Ensure that the C++ Thread and OSThread structures aren't freed before we operate - MutexLockerEx ml(current_thread->threadObj() == thread_oop ? NULL : Threads_lock); - // We need to re-resolve the java_thread, since a GC might have happened during the - // acquire of the lock - - JavaThread* java_thread = java_lang_Thread::thread(JNIHandles::resolve_external_guard(thread)); - NULL_CHECK(java_thread, JVMTI_ERROR_THREAD_NOT_ALIVE); + JavaThread* java_thread = NULL; + ThreadsListHandle tlh(current_thread); + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, NULL); + if (err != JVMTI_ERROR_NONE) { + return err; + } Thread::interrupt(java_thread); @@ -1094,16 +1106,28 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) { HandleMark hm; JavaThread* current_thread = JavaThread::current(); + ThreadsListHandle tlh(current_thread); // if thread is NULL the current thread is used - oop thread_oop; + oop thread_oop = NULL; if (thread == NULL) { thread_oop = current_thread->threadObj(); + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { + return JVMTI_ERROR_INVALID_THREAD; + } } else { - thread_oop = JNIHandles::resolve_external_guard(thread); + JavaThread* java_thread = NULL; + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, &thread_oop); + if (err != JVMTI_ERROR_NONE) { + // We got an error code so we don't have a JavaThread *, but + // only return an error from here if we didn't get a valid + // thread_oop. + if (thread_oop == NULL) { + return err; + } + // We have a valid thread_oop so we can return some thread info. + } } - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) - return JVMTI_ERROR_INVALID_THREAD; Handle thread_obj(current_thread, thread_oop); Handle name; @@ -1272,17 +1296,31 @@ JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_p // arg - NULL is a valid value, must be checked jvmtiError JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) { - oop thread_oop = JNIHandles::resolve_external_guard(thread); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { + JavaThread* current_thread = JavaThread::current(); + + JavaThread* java_thread = NULL; + oop thread_oop = NULL; + ThreadsListHandle tlh(current_thread); + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, &thread_oop); + if (err != JVMTI_ERROR_NONE) { + // We got an error code so we don't have a JavaThread *, but + // only return an error from here if we didn't get a valid + // thread_oop. + if (thread_oop == NULL) { + return err; + } + // We have a valid thread_oop. + } + + if (java_thread != NULL) { + // 'thread' refers to an existing JavaThread. return JVMTI_ERROR_INVALID_THREAD; } + if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) { return JVMTI_ERROR_INVALID_PRIORITY; } - //Thread-self - JavaThread* current_thread = JavaThread::current(); - Handle thread_hndl(current_thread, thread_oop); { MutexLocker mu(Threads_lock); // grab Threads_lock @@ -1292,7 +1330,9 @@ JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* ar // At this point it may be possible that no osthread was created for the // JavaThread due to lack of memory. if (new_thread == NULL || new_thread->osthread() == NULL) { - if (new_thread) delete new_thread; + if (new_thread != NULL) { + new_thread->smr_delete(); + } return JVMTI_ERROR_OUT_OF_MEMORY; } @@ -1394,36 +1434,53 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth int ngroups = 0; int hidden_threads = 0; - ResourceMark rm; - HandleMark hm; + ResourceMark rm(current_thread); + HandleMark hm(current_thread); Handle group_hdl(current_thread, group_obj); - { MutexLocker mu(Threads_lock); + { // Cannot allow thread or group counts to change. + MutexLocker mu(Threads_lock); nthreads = java_lang_ThreadGroup::nthreads(group_hdl()); ngroups = java_lang_ThreadGroup::ngroups(group_hdl()); if (nthreads > 0) { + ThreadsListHandle tlh(current_thread); objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl()); assert(nthreads <= threads->length(), "too many threads"); thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads); for (int i=0, j=0; iobj_at(i); assert(thread_obj != NULL, "thread_obj is NULL"); - JavaThread *javathread = java_lang_Thread::thread(thread_obj); - // Filter out hidden java threads. - if (javathread != NULL && javathread->is_hidden_from_external_view()) { - hidden_threads++; - continue; + JavaThread *java_thread = NULL; + jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &java_thread); + if (err == JVMTI_ERROR_NONE) { + // Have a valid JavaThread*. + if (java_thread->is_hidden_from_external_view()) { + // Filter out hidden java threads. + hidden_threads++; + continue; + } + } else { + // We couldn't convert thread_obj into a JavaThread*. + if (err == JVMTI_ERROR_INVALID_THREAD) { + // The thread_obj does not refer to a java.lang.Thread object + // so skip it. + hidden_threads++; + continue; + } + // We have a valid thread_obj, but no JavaThread*; the caller + // can still have limited use for the thread_obj. } thread_objs[j++] = Handle(current_thread, thread_obj); } nthreads -= hidden_threads; - } + } // ThreadsListHandle is destroyed here. + if (ngroups > 0) { objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl()); - assert(ngroups <= groups->length(), "too many threads"); + assert(ngroups <= groups->length(), "too many groups"); group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups); for (int i=0; iobj_at(i); @@ -1556,7 +1613,7 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) { } // Check if java_thread is fully suspended - if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) { + if (!java_thread->is_thread_fully_suspended(true /* wait for suspend completion */, &debug_bits)) { return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } // Check to see if a PopFrame was already in progress @@ -1686,8 +1743,8 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) { return JVMTI_ERROR_THREAD_NOT_ALIVE; } - if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) { - return JVMTI_ERROR_THREAD_NOT_SUSPENDED; + if (!java_thread->is_thread_fully_suspended(true, &debug_bits)) { + return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } if (TraceJVMTICalls) { diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 2e8918c57e1..18d59fbc2e8 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -44,6 +44,7 @@ #include "runtime/objectMonitor.inline.hpp" #include "runtime/signature.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vframe_hp.hpp" #include "runtime/vmThread.hpp" @@ -487,37 +488,6 @@ JvmtiEnvBase::set_event_callbacks(const jvmtiEventCallbacks* callbacks, } } -// Called from JVMTI entry points which perform stack walking. If the -// associated JavaThread is the current thread, then wait_for_suspend -// is not used. Otherwise, it determines if we should wait for the -// "other" thread to complete external suspension. (NOTE: in future -// releases the suspension mechanism should be reimplemented so this -// is not necessary.) -// -bool -JvmtiEnvBase::is_thread_fully_suspended(JavaThread* thr, bool wait_for_suspend, uint32_t *bits) { - // "other" threads require special handling - if (thr != JavaThread::current()) { - if (wait_for_suspend) { - // We are allowed to wait for the external suspend to complete - // so give the other thread a chance to get suspended. - if (!thr->wait_for_ext_suspend_completion(SuspendRetryCount, - SuspendRetryDelay, bits)) { - // didn't make it so let the caller know - return false; - } - } - // We aren't allowed to wait for the external suspend to complete - // so if the other thread isn't externally suspended we need to - // let the caller know. - else if (!thr->is_ext_suspend_completed_with_lock(bits)) { - return false; - } - } - - return true; -} - // In the fullness of time, all users of the method should instead // directly use allocate, besides being cleaner and faster, this will @@ -560,19 +530,6 @@ JvmtiEnvBase::new_jthreadGroupArray(int length, Handle *handles) { return (jthreadGroup *) new_jobjectArray(length,handles); } - -JavaThread * -JvmtiEnvBase::get_JavaThread(jthread jni_thread) { - oop t = JNIHandles::resolve_external_guard(jni_thread); - if (t == NULL || !t->is_a(SystemDictionary::Thread_klass())) { - return NULL; - } - // The following returns NULL if the thread has not yet run or is in - // process of exiting - return java_lang_Thread::thread(t); -} - - // return the vframe on the specified thread and depth, NULL if no such frame vframe* JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) { @@ -670,7 +627,7 @@ JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThre uint32_t debug_bits = 0; #endif assert((SafepointSynchronize::is_at_safepoint() || - is_thread_fully_suspended(java_thread, false, &debug_bits)), + java_thread->is_thread_fully_suspended(false, &debug_bits)), "at safepoint or target thread is suspended"); oop obj = NULL; ObjectMonitor *mon = java_thread->current_waiting_monitor(); @@ -709,7 +666,7 @@ JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_th uint32_t debug_bits = 0; #endif assert((SafepointSynchronize::is_at_safepoint() || - is_thread_fully_suspended(java_thread, false, &debug_bits)), + java_thread->is_thread_fully_suspended(false, &debug_bits)), "at safepoint or target thread is suspended"); if (java_thread->has_last_Java_frame()) { @@ -831,7 +788,7 @@ JvmtiEnvBase::get_stack_trace(JavaThread *java_thread, uint32_t debug_bits = 0; #endif assert((SafepointSynchronize::is_at_safepoint() || - is_thread_fully_suspended(java_thread, false, &debug_bits)), + java_thread->is_thread_fully_suspended(false, &debug_bits)), "at safepoint or target thread is suspended"); int count = 0; if (java_thread->has_last_Java_frame()) { @@ -914,7 +871,7 @@ JvmtiEnvBase::get_frame_location(JavaThread *java_thread, jint depth, uint32_t debug_bits = 0; #endif assert((SafepointSynchronize::is_at_safepoint() || - is_thread_fully_suspended(java_thread, false, &debug_bits)), + java_thread->is_thread_fully_suspended(false, &debug_bits)), "at safepoint or target thread is suspended"); Thread* current_thread = Thread::current(); ResourceMark rm(current_thread); @@ -976,7 +933,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // first derive the object's owner and entry_count (if any) { // Revoke any biases before querying the mark word - if (SafepointSynchronize::is_at_safepoint()) { + if (at_safepoint) { BiasedLocking::revoke_at_safepoint(hobj); } else { BiasedLocking::revoke_and_rebias(hobj, false, calling_thread); @@ -1008,11 +965,11 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec } if (owner != NULL) { + // Use current thread since function can be called from a + // JavaThread or the VMThread. + ThreadsListHandle tlh; // This monitor is owned so we have to find the owning JavaThread. - // Since owning_thread_from_monitor_owner() grabs a lock, GC can - // move our object at this point. However, our owner value is safe - // since it is either the Lock word on a stack or a JavaThread *. - owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint); + owning_thread = Threads::owning_thread_from_monitor_owner(tlh.list(), owner); // Cannot assume (owning_thread != NULL) here because this function // may not have been called at a safepoint and the owning_thread // might not be suspended. @@ -1021,7 +978,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // or it has to be suspended. Any of these conditions will prevent both // contending and waiting threads from modifying the state of // the monitor. - if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) { + if (!at_safepoint && !owning_thread->is_thread_fully_suspended(true, &debug_bits)) { // Don't worry! This return of JVMTI_ERROR_THREAD_NOT_SUSPENDED // will not make it back to the JVM/TI agent. The error code will // get intercepted in JvmtiEnv::GetObjectMonitorUsage() which @@ -1033,7 +990,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec ret.owner = (jthread)jni_reference(calling_thread, th); } // implied else: no owner - } + } // ThreadsListHandle is destroyed here. if (owning_thread != NULL) { // monitor is owned // The recursions field of a monitor does not reflect recursions @@ -1084,13 +1041,15 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec if (ret.waiter_count > 0) { // we have contending and/or waiting threads HandleMark hm; + // Use current thread since function can be called from a + // JavaThread or the VMThread. + ThreadsListHandle tlh; if (nWant > 0) { // we have contending threads ResourceMark rm; // get_pending_threads returns only java thread so we do not need to - // check for non java threads. - GrowableArray* wantList = Threads::get_pending_threads( - nWant, (address)mon, !at_safepoint); + // check for non java threads. + GrowableArray* wantList = Threads::get_pending_threads(tlh.list(), nWant, (address)mon); if (wantList->length() < nWant) { // robustness: the pending list has gotten smaller nWant = wantList->length(); @@ -1101,7 +1060,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // thread could potentially change the state of the monitor by // entering it. The JVM/TI spec doesn't allow this. if (owning_thread == NULL && !at_safepoint & - !JvmtiEnv::is_thread_fully_suspended(pending_thread, true, &debug_bits)) { + !pending_thread->is_thread_fully_suspended(true, &debug_bits)) { if (ret.owner != NULL) { destroy_jni_reference(calling_thread, ret.owner); } @@ -1139,7 +1098,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec waiter = mon->next_waiter(waiter); } } - } + } // ThreadsListHandle is destroyed here. // Adjust count. nWant and nWait count values may be less than original. ret.waiter_count = nWant + nWait; @@ -1291,14 +1250,23 @@ VM_GetThreadListStackTraces::doit() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); ResourceMark rm; + ThreadsListHandle tlh; for (int i = 0; i < _thread_count; ++i) { jthread jt = _thread_list[i]; - oop thread_oop = JNIHandles::resolve_external_guard(jt); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { - set_result(JVMTI_ERROR_INVALID_THREAD); - return; + JavaThread* java_thread = NULL; + oop thread_oop = NULL; + jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), jt, &java_thread, &thread_oop); + if (err != JVMTI_ERROR_NONE) { + // We got an error code so we don't have a JavaThread *, but + // only return an error from here if we didn't get a valid + // thread_oop. + if (thread_oop == NULL) { + set_result(err); + return; + } + // We have a valid thread_oop. } - fill_frames(jt, java_lang_Thread::thread(thread_oop), thread_oop); + fill_frames(jt, java_thread, thread_oop); } allocate_and_fill_stacks(_thread_count); } @@ -1309,7 +1277,7 @@ VM_GetAllStackTraces::doit() { ResourceMark rm; _final_thread_count = 0; - for (JavaThread *jt = Threads::first(); jt != NULL; jt = jt->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { oop thread_oop = jt->threadObj(); if (thread_oop != NULL && !jt->is_exiting() && @@ -1404,9 +1372,7 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState } // Check if java_thread is fully suspended - if (!is_thread_fully_suspended(java_thread, - true /* wait for suspend completion */, - &debug_bits)) { + if (!java_thread->is_thread_fully_suspended(true /* wait for suspend completion */, &debug_bits)) { return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } @@ -1521,3 +1487,79 @@ JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobje return JVMTI_ERROR_NONE; } +void +VM_UpdateForPopTopFrame::doit() { + JavaThread* jt = _state->get_thread(); + ThreadsListHandle tlh; + if (jt != NULL && tlh.includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) { + _state->update_for_pop_top_frame(); + } else { + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + } +} + +void +VM_SetFramePop::doit() { + JavaThread* jt = _state->get_thread(); + ThreadsListHandle tlh; + if (jt != NULL && tlh.includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) { + int frame_number = _state->count_frames() - _depth; + _state->env_thread_state((JvmtiEnvBase*)_env)->set_frame_pop(frame_number); + } else { + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + } +} + +void +VM_GetOwnedMonitorInfo::doit() { + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + ThreadsListHandle tlh; + if (_java_thread != NULL && tlh.includes(_java_thread) + && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread, + _owned_monitors_list); + } +} + +void +VM_GetCurrentContendedMonitor::doit() { + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + ThreadsListHandle tlh; + if (_java_thread != NULL && tlh.includes(_java_thread) + && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr); + } +} + +void +VM_GetStackTrace::doit() { + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + ThreadsListHandle tlh; + if (_java_thread != NULL && tlh.includes(_java_thread) + && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, + _start_depth, _max_count, + _frame_buffer, _count_ptr); + } +} + +void +VM_GetFrameCount::doit() { + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + JavaThread* jt = _state->get_thread(); + ThreadsListHandle tlh; + if (jt != NULL && tlh.includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) { + _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); + } +} + +void +VM_GetFrameLocation::doit() { + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + ThreadsListHandle tlh; + if (_java_thread != NULL && tlh.includes(_java_thread) + && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth, + _method_ptr, _location_ptr); + } +} diff --git a/src/hotspot/share/prims/jvmtiEnvBase.hpp b/src/hotspot/share/prims/jvmtiEnvBase.hpp index c5786aca4af..84e3f54ae6d 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.hpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp @@ -280,9 +280,6 @@ class JvmtiEnvBase : public CHeapObj { jthread * new_jthreadArray(int length, Handle *handles); jthreadGroup * new_jthreadGroupArray(int length, Handle *handles); - // convert from JNIHandle to JavaThread * - JavaThread * get_JavaThread(jthread jni_thread); - // convert to a jni jclass from a non-null Klass* jclass get_jni_class_non_null(Klass* k); @@ -297,11 +294,6 @@ class JvmtiEnvBase : public CHeapObj { public: // get a field descriptor for the specified class and field static bool get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd); - // test for suspend - most (all?) of these should go away - static bool is_thread_fully_suspended(JavaThread *thread, - bool wait_for_suspend, - uint32_t *bits); - // JVMTI API helper functions which are called at safepoint or thread is suspended. jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr); @@ -360,14 +352,7 @@ public: } VMOp_Type type() const { return VMOp_UpdateForPopTopFrame; } jvmtiError result() { return _result; } - void doit() { - JavaThread* jt = _state->get_thread(); - if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) { - _state->update_for_pop_top_frame(); - } else { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - } - } + void doit(); }; // VM operation to set frame pop. @@ -390,15 +375,7 @@ public: bool allow_nested_vm_operations() const { return true; } VMOp_Type type() const { return VMOp_SetFramePop; } jvmtiError result() { return _result; } - void doit() { - JavaThread* jt = _state->get_thread(); - if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) { - int frame_number = _state->count_frames() - _depth; - _state->env_thread_state((JvmtiEnvBase*)_env)->set_frame_pop(frame_number); - } else { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - } - } + void doit(); }; @@ -422,14 +399,7 @@ public: _result = JVMTI_ERROR_NONE; } VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; } - void doit() { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - if (Threads::includes(_java_thread) && !_java_thread->is_exiting() - && _java_thread->threadObj() != NULL) { - _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread, - _owned_monitors_list); - } - } + void doit(); jvmtiError result() { return _result; } }; @@ -476,13 +446,7 @@ public: } VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; } jvmtiError result() { return _result; } - void doit() { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - if (Threads::includes(_java_thread) && !_java_thread->is_exiting() && - _java_thread->threadObj() != NULL) { - _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr); - } - } + void doit(); }; // VM operation to get stack trace at safepoint. @@ -509,15 +473,7 @@ public: } jvmtiError result() { return _result; } VMOp_Type type() const { return VMOp_GetStackTrace; } - void doit() { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - if (Threads::includes(_java_thread) && !_java_thread->is_exiting() - && _java_thread->threadObj() != NULL) { - _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, - _start_depth, _max_count, - _frame_buffer, _count_ptr); - } - } + void doit(); }; // forward declaration @@ -607,13 +563,7 @@ public: } VMOp_Type type() const { return VMOp_GetFrameCount; } jvmtiError result() { return _result; } - void doit() { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - JavaThread* jt = _state->get_thread(); - if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) { - _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); - } - } + void doit(); }; // VM operation to frame location at safepoint. @@ -637,14 +587,7 @@ public: } VMOp_Type type() const { return VMOp_GetFrameLocation; } jvmtiError result() { return _result; } - void doit() { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - if (Threads::includes(_java_thread) && !_java_thread->is_exiting() && - _java_thread->threadObj() != NULL) { - _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth, - _method_ptr, _location_ptr); - } - } + void doit(); }; diff --git a/src/hotspot/share/prims/jvmtiEnvThreadState.cpp b/src/hotspot/share/prims/jvmtiEnvThreadState.cpp index d7ffd105596..643c4409274 100644 --- a/src/hotspot/share/prims/jvmtiEnvThreadState.cpp +++ b/src/hotspot/share/prims/jvmtiEnvThreadState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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,6 +35,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/javaCalls.hpp" #include "runtime/signature.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.hpp" #include "runtime/vm_operations.hpp" diff --git a/src/hotspot/share/prims/jvmtiEnvThreadState.hpp b/src/hotspot/share/prims/jvmtiEnvThreadState.hpp index c25e5e34547..9b947f93e94 100644 --- a/src/hotspot/share/prims/jvmtiEnvThreadState.hpp +++ b/src/hotspot/share/prims/jvmtiEnvThreadState.hpp @@ -27,7 +27,6 @@ #include "jvmtifiles/jvmti.h" #include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" #include "oops/instanceKlass.hpp" #include "prims/jvmtiEventController.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp b/src/hotspot/share/prims/jvmtiEventController.cpp index cdad3264c82..3c919c61106 100644 --- a/src/hotspot/share/prims/jvmtiEventController.cpp +++ b/src/hotspot/share/prims/jvmtiEventController.cpp @@ -33,7 +33,8 @@ #include "prims/jvmtiImpl.hpp" #include "prims/jvmtiThreadState.inline.hpp" #include "runtime/frame.hpp" -#include "runtime/thread.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vframe_hp.hpp" #include "runtime/vmThread.hpp" @@ -580,13 +581,10 @@ JvmtiEventControllerPrivate::recompute_enabled() { // filtered events and there weren't last time if ( (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 && (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) { - { - MutexLocker mu(Threads_lock); //hold the Threads_lock for the iteration - for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) { - // state_for_while_locked() makes tp->is_exiting() check - JvmtiThreadState::state_for_while_locked(tp); // create the thread state if missing - } - }// release Threads_lock + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) { + // state_for_while_locked() makes tp->is_exiting() check + JvmtiThreadState::state_for_while_locked(tp); // create the thread state if missing + } } // compute and set thread-filtered events diff --git a/src/hotspot/share/prims/jvmtiEventController.hpp b/src/hotspot/share/prims/jvmtiEventController.hpp index 90b000ccfb3..c250c2f4772 100644 --- a/src/hotspot/share/prims/jvmtiEventController.hpp +++ b/src/hotspot/share/prims/jvmtiEventController.hpp @@ -27,7 +27,6 @@ #include "jvmtifiles/jvmti.h" #include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" #include "utilities/globalDefinitions.hpp" // forward declaration diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index 7d8de627808..631ddcdabaa 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -53,6 +53,7 @@ #include "runtime/objectMonitor.inline.hpp" #include "runtime/os.inline.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "services/serviceUtil.hpp" #include "utilities/macros.hpp" @@ -721,6 +722,108 @@ JvmtiExport::get_all_native_method_prefixes(int* count_ptr) { } } +// Convert an external thread reference to a JavaThread found on the +// specified ThreadsList. The ThreadsListHandle in the caller "protects" +// the returned JavaThread *. +// +// If thread_oop_p is not NULL, then the caller wants to use the oop +// after this call so the oop is returned. On success, *jt_pp is set +// to the converted JavaThread * and JVMTI_ERROR_NONE is returned. +// On error, returns various JVMTI_ERROR_* values. +// +jvmtiError +JvmtiExport::cv_external_thread_to_JavaThread(ThreadsList * t_list, + jthread thread, + JavaThread ** jt_pp, + oop * thread_oop_p) { + assert(t_list != NULL, "must have a ThreadsList"); + assert(jt_pp != NULL, "must have a return JavaThread pointer"); + // thread_oop_p is optional so no assert() + + oop thread_oop = JNIHandles::resolve_external_guard(thread); + if (thread_oop == NULL) { + // NULL jthread, GC'ed jthread or a bad JNI handle. + return JVMTI_ERROR_INVALID_THREAD; + } + // Looks like an oop at this point. + + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { + // The oop is not a java.lang.Thread. + return JVMTI_ERROR_INVALID_THREAD; + } + // Looks like a java.lang.Thread oop at this point. + + if (thread_oop_p != NULL) { + // Return the oop to the caller; the caller may still want + // the oop even if this function returns an error. + *thread_oop_p = thread_oop; + } + + JavaThread * java_thread = java_lang_Thread::thread(thread_oop); + if (java_thread == NULL) { + // The java.lang.Thread does not contain a JavaThread * so it has + // not yet run or it has died. + return JVMTI_ERROR_THREAD_NOT_ALIVE; + } + // Looks like a live JavaThread at this point. + + // We do not check the EnableThreadSMRExtraValidityChecks option + // for this includes() call because JVM/TI's spec is tighter. + if (!t_list->includes(java_thread)) { + // Not on the JavaThreads list so it is not alive. + return JVMTI_ERROR_THREAD_NOT_ALIVE; + } + + // Return a live JavaThread that is "protected" by the + // ThreadsListHandle in the caller. + *jt_pp = java_thread; + + return JVMTI_ERROR_NONE; +} + +// Convert an oop to a JavaThread found on the specified ThreadsList. +// The ThreadsListHandle in the caller "protects" the returned +// JavaThread *. +// +// On success, *jt_pp is set to the converted JavaThread * and +// JVMTI_ERROR_NONE is returned. On error, returns various +// JVMTI_ERROR_* values. +// +jvmtiError +JvmtiExport::cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop, + JavaThread ** jt_pp) { + assert(t_list != NULL, "must have a ThreadsList"); + assert(thread_oop != NULL, "must have an oop"); + assert(jt_pp != NULL, "must have a return JavaThread pointer"); + + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { + // The oop is not a java.lang.Thread. + return JVMTI_ERROR_INVALID_THREAD; + } + // Looks like a java.lang.Thread oop at this point. + + JavaThread * java_thread = java_lang_Thread::thread(thread_oop); + if (java_thread == NULL) { + // The java.lang.Thread does not contain a JavaThread * so it has + // not yet run or it has died. + return JVMTI_ERROR_THREAD_NOT_ALIVE; + } + // Looks like a live JavaThread at this point. + + // We do not check the EnableThreadSMRExtraValidityChecks option + // for this includes() call because JVM/TI's spec is tighter. + if (!t_list->includes(java_thread)) { + // Not on the JavaThreads list so it is not alive. + return JVMTI_ERROR_THREAD_NOT_ALIVE; + } + + // Return a live JavaThread that is "protected" by the + // ThreadsListHandle in the caller. + *jt_pp = java_thread; + + return JVMTI_ERROR_NONE; +} + class JvmtiClassFileLoadHookPoster : public StackObj { private: Symbol* _h_name; @@ -2475,7 +2578,7 @@ extern "C" { jint JvmtiExport::load_agent_library(const char *agent, const char *absParam, const char *options, outputStream* st) { - char ebuf[1024]; + char ebuf[1024] = {0}; char buffer[JVM_MAXPATHLEN]; void* library = NULL; jint result = JNI_ERR; @@ -2525,6 +2628,8 @@ jint JvmtiExport::load_agent_library(const char *agent, const char *absParam, if (!agent_lib->is_static_lib()) { os::dll_unload(library); } + st->print_cr("%s is not available in %s", + on_attach_symbols[0], agent_lib->name()); delete agent_lib; } else { // Invoke the Agent_OnAttach function @@ -2551,9 +2656,14 @@ jint JvmtiExport::load_agent_library(const char *agent, const char *absParam, } // Agent_OnAttach executed so completion status is JNI_OK - st->print_cr("%d", result); + st->print_cr("return code: %d", result); result = JNI_OK; } + } else { + st->print_cr("%s was not loaded.", agent); + if (*ebuf != '\0') { + st->print_cr("%s", ebuf); + } } return result; } @@ -2685,8 +2795,7 @@ void JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(OopClosure* f) { return; } - // Runs at safepoint. So no need to acquire Threads_lock. - for (JavaThread *jthr = Threads::first(); jthr != NULL; jthr = jthr->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jthr = jtiwh.next(); ) { JvmtiThreadState *state = jthr->jvmti_thread_state(); if (state != NULL) { JvmtiVMObjectAllocEventCollector *collector; diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp index 7bae70b626e..3421150cab2 100644 --- a/src/hotspot/share/prims/jvmtiExport.hpp +++ b/src/hotspot/share/prims/jvmtiExport.hpp @@ -399,6 +399,14 @@ class JvmtiExport : public AllStatic { // SetNativeMethodPrefix support static char** get_all_native_method_prefixes(int* count_ptr) NOT_JVMTI_RETURN_(NULL); + + // JavaThread lifecycle support: + static jvmtiError cv_external_thread_to_JavaThread(ThreadsList * t_list, + jthread thread, + JavaThread ** jt_pp, + oop * thread_oop_p); + static jvmtiError cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop, + JavaThread ** jt_pp); }; // Support class used by JvmtiDynamicCodeEventCollector and others. It diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp index 4869a653144..82cdabdbd9b 100644 --- a/src/hotspot/share/prims/jvmtiImpl.cpp +++ b/src/hotspot/share/prims/jvmtiImpl.cpp @@ -46,6 +46,7 @@ #include "runtime/serviceThread.hpp" #include "runtime/signature.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vframe_hp.hpp" #include "runtime/vm_operations.hpp" @@ -878,10 +879,9 @@ bool JvmtiSuspendControl::resume(JavaThread *java_thread) { void JvmtiSuspendControl::print() { #ifndef PRODUCT - MutexLocker mu(Threads_lock); LogStreamHandle(Trace, jvmti) log_stream; log_stream.print("Suspended Threads: ["); - for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { #ifdef JVMTI_TRACE const char *name = JvmtiTrace::safe_get_thread_name(thread); #else diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index c73842e0500..abca485f97b 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -43,6 +43,7 @@ #include "oops/oop.inline.hpp" #include "prims/jvmtiImpl.hpp" #include "prims/jvmtiRedefineClasses.hpp" +#include "prims/jvmtiThreadState.inline.hpp" #include "prims/resolvedMethodTable.hpp" #include "prims/methodComparator.hpp" #include "runtime/deoptimization.hpp" diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index 3a45b2c8eff..6ea720a1e44 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -45,6 +45,8 @@ #include "runtime/mutex.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/reflectionUtils.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" @@ -3174,7 +3176,7 @@ inline bool VM_HeapWalkOperation::collect_stack_roots(JavaThread* java_thread, // stack to find all references and local JNI refs. inline bool VM_HeapWalkOperation::collect_stack_roots() { JNILocalRootsClosure blk; - for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { oop threadObj = thread->threadObj(); if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) { // Collect the simple root for this thread before we diff --git a/src/hotspot/share/prims/jvmtiThreadState.hpp b/src/hotspot/share/prims/jvmtiThreadState.hpp index 9dfb9b85309..16a0a3455c7 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.hpp +++ b/src/hotspot/share/prims/jvmtiThreadState.hpp @@ -27,7 +27,6 @@ #include "jvmtifiles/jvmti.h" #include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" #include "prims/jvmtiEventController.hpp" #include "runtime/thread.hpp" #include "utilities/growableArray.hpp" @@ -336,34 +335,10 @@ class JvmtiThreadState : public CHeapObj { // already holding JvmtiThreadState_lock - retrieve or create JvmtiThreadState // Can return NULL if JavaThread is exiting. - inline static JvmtiThreadState *state_for_while_locked(JavaThread *thread) { - assert(JvmtiThreadState_lock->is_locked(), "sanity check"); - - JvmtiThreadState *state = thread->jvmti_thread_state(); - if (state == NULL) { - if (thread->is_exiting()) { - // don't add a JvmtiThreadState to a thread that is exiting - return NULL; - } - - state = new JvmtiThreadState(thread); - } - return state; - } - + static JvmtiThreadState *state_for_while_locked(JavaThread *thread); // retrieve or create JvmtiThreadState // Can return NULL if JavaThread is exiting. - inline static JvmtiThreadState *state_for(JavaThread *thread) { - JvmtiThreadState *state = thread->jvmti_thread_state(); - if (state == NULL) { - MutexLocker mu(JvmtiThreadState_lock); - // check again with the lock held - state = state_for_while_locked(thread); - } else { - CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); - } - return state; - } + static JvmtiThreadState *state_for(JavaThread *thread); // JVMTI ForceEarlyReturn support diff --git a/src/hotspot/share/prims/jvmtiThreadState.inline.hpp b/src/hotspot/share/prims/jvmtiThreadState.inline.hpp index 1b9926fb1da..e3859a3334d 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.inline.hpp +++ b/src/hotspot/share/prims/jvmtiThreadState.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2017, 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 @@ -68,4 +68,31 @@ void JvmtiThreadState::set_head_env_thread_state(JvmtiEnvThreadState* ets) { _head_env_thread_state = ets; } +inline JvmtiThreadState* JvmtiThreadState::state_for_while_locked(JavaThread *thread) { + assert(JvmtiThreadState_lock->is_locked(), "sanity check"); + + JvmtiThreadState *state = thread->jvmti_thread_state(); + if (state == NULL) { + if (thread->is_exiting()) { + // don't add a JvmtiThreadState to a thread that is exiting + return NULL; + } + + state = new JvmtiThreadState(thread); + } + return state; +} + +inline JvmtiThreadState* JvmtiThreadState::state_for(JavaThread *thread) { + JvmtiThreadState *state = thread->jvmti_thread_state(); + if (state == NULL) { + MutexLocker mu(JvmtiThreadState_lock); + // check again with the lock held + state = state_for_while_locked(thread); + } else { + CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); + } + return state; +} + #endif // SHARE_VM_PRIMS_JVMTITHREADSTATE_INLINE_HPP diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp index 8374755490e..2da189889fb 100644 --- a/src/hotspot/share/prims/methodHandles.cpp +++ b/src/hotspot/share/prims/methodHandles.cpp @@ -1029,6 +1029,26 @@ void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) { } } +void MethodHandles::trace_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid) { + if (TraceMethodHandles) { + const char* name = vmIntrinsics::name_at(iid); + if (*name == '_') name += 1; + const size_t len = strlen(name) + 50; + char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal); + const char* suffix = ""; + if (is_signature_polymorphic(iid)) { + if (is_signature_polymorphic_static(iid)) + suffix = "/static"; + else + suffix = "/private"; + } + jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix); + trace_method_handle(_masm, qname); + // Note: Don't free the allocated char array because it's used + // during runtime. + } +} + // // Here are the native methods in java.lang.invoke.MethodHandleNatives // They are the private interface between this JVM and the HotSpot-specific diff --git a/src/hotspot/share/prims/methodHandles.hpp b/src/hotspot/share/prims/methodHandles.hpp index df83f23daf3..2be115636af 100644 --- a/src/hotspot/share/prims/methodHandles.hpp +++ b/src/hotspot/share/prims/methodHandles.hpp @@ -195,25 +195,7 @@ public: // Tracing static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN; - static void trace_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid) { - if (TraceMethodHandles) { - const char* name = vmIntrinsics::name_at(iid); - if (*name == '_') name += 1; - const size_t len = strlen(name) + 50; - char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal); - const char* suffix = ""; - if (is_signature_polymorphic(iid)) { - if (is_signature_polymorphic_static(iid)) - suffix = "/static"; - else - suffix = "/private"; - } - jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix); - trace_method_handle(_masm, qname); - // Note: Don't free the allocated char array because it's used - // during runtime. - } - } + static void trace_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid); }; //------------------------------------------------------------------------------ diff --git a/src/hotspot/share/prims/perf.cpp b/src/hotspot/share/prims/perf.cpp index ba019e04cb2..cf93aaeb99b 100644 --- a/src/hotspot/share/prims/perf.cpp +++ b/src/hotspot/share/prims/perf.cpp @@ -30,7 +30,7 @@ #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/interfaceSupport.hpp" -#include "runtime/perfData.hpp" +#include "runtime/perfData.inline.hpp" #include "runtime/perfMemory.hpp" /* diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp index c6796d53a3a..a8d13138507 100644 --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -39,6 +39,8 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/orderAccess.inline.hpp" #include "runtime/reflection.hpp" +#include "runtime/thread.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vm_version.hpp" #include "services/threadService.hpp" #include "trace/tracing.hpp" @@ -144,18 +146,25 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { * Normalizes values and wraps accesses in * JavaThread::doing_unsafe_access() if needed. */ +template class MemoryAccess : StackObj { JavaThread* _thread; oop _obj; ptrdiff_t _offset; - // Resolves and returns the address of the memory access - void* addr() { - return index_oop_from_field_offset_long(_obj, _offset); + // Resolves and returns the address of the memory access. + // This raw memory access may fault, so we make sure it happens within the + // guarded scope by making the access volatile at least. Since the store + // of Thread::set_doing_unsafe_access() is also volatile, these accesses + // can not be reordered by the compiler. Therefore, if the access triggers + // a fault, we will know that Thread::doing_unsafe_access() returns true. + volatile T* addr() { + void* addr = index_oop_from_field_offset_long(_obj, _offset); + return static_cast(addr); } - template - T normalize_for_write(T x) { + template + U normalize_for_write(U x) { return x; } @@ -163,8 +172,8 @@ class MemoryAccess : StackObj { return x & 1; } - template - T normalize_for_read(T x) { + template + U normalize_for_read(U x) { return x; } @@ -197,11 +206,10 @@ public: assert_field_offset_sane(_obj, offset); } - template T get() { if (oopDesc::is_null(_obj)) { GuardUnsafeAccess guard(_thread); - T ret = RawAccess<>::load((T*)addr()); + T ret = RawAccess<>::load(addr()); return normalize_for_read(ret); } else { T ret = HeapAccess<>::load_at(_obj, _offset); @@ -209,22 +217,20 @@ public: } } - template void put(T x) { if (oopDesc::is_null(_obj)) { GuardUnsafeAccess guard(_thread); - RawAccess<>::store((T*)addr(), normalize_for_write(x)); + RawAccess<>::store(addr(), normalize_for_write(x)); } else { HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x)); } } - template T get_volatile() { if (oopDesc::is_null(_obj)) { GuardUnsafeAccess guard(_thread); - volatile T ret = RawAccess::load((volatile T*)addr()); + volatile T ret = RawAccess::load(addr()); return normalize_for_read(ret); } else { T ret = HeapAccess::load_at(_obj, _offset); @@ -232,11 +238,10 @@ public: } } - template void put_volatile(T x) { if (oopDesc::is_null(_obj)) { GuardUnsafeAccess guard(_thread); - RawAccess::store((volatile T*)addr(), normalize_for_write(x)); + RawAccess::store(addr(), normalize_for_write(x)); } else { HeapAccess::store_at(_obj, _offset, normalize_for_write(x)); } @@ -294,11 +299,11 @@ UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) { #define DEFINE_GETSETOOP(java_type, Type) \ \ UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ - return MemoryAccess(thread, obj, offset).get(); \ + return MemoryAccess(thread, obj, offset).get(); \ } UNSAFE_END \ \ UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ - MemoryAccess(thread, obj, offset).put(x); \ + MemoryAccess(thread, obj, offset).put(x); \ } UNSAFE_END \ \ // END DEFINE_GETSETOOP. @@ -317,11 +322,11 @@ DEFINE_GETSETOOP(jdouble, Double); #define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \ \ UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ - return MemoryAccess(thread, obj, offset).get_volatile(); \ + return MemoryAccess(thread, obj, offset).get_volatile(); \ } UNSAFE_END \ \ UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ - MemoryAccess(thread, obj, offset).put_volatile(x); \ + MemoryAccess(thread, obj, offset).put_volatile(x); \ } UNSAFE_END \ \ // END DEFINE_GETSETOOP_VOLATILE. @@ -937,8 +942,12 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) Parker* p = NULL; if (jthread != NULL) { - oop java_thread = JNIHandles::resolve_non_null(jthread); + ThreadsListHandle tlh; + JavaThread* thr = NULL; + oop java_thread = NULL; + (void) tlh.cv_internal_thread_to_JavaThread(jthread, &thr, &java_thread); if (java_thread != NULL) { + // This is a valid oop. jlong lp = java_lang_Thread::park_event(java_thread); if (lp != 0) { // This cast is OK even though the jlong might have been read @@ -946,22 +955,19 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) // always be zero anyway and the value set is always the same p = (Parker*)addr_from_java(lp); } else { - // Grab lock if apparently null or using older version of library - MutexLocker mu(Threads_lock); - java_thread = JNIHandles::resolve_non_null(jthread); - - if (java_thread != NULL) { - JavaThread* thr = java_lang_Thread::thread(java_thread); - if (thr != NULL) { - p = thr->parker(); - if (p != NULL) { // Bind to Java thread for next time. - java_lang_Thread::set_park_event(java_thread, addr_to_java(p)); - } + // Not cached in the java.lang.Thread oop yet (could be an + // older version of library). + if (thr != NULL) { + // The JavaThread is alive. + p = thr->parker(); + if (p != NULL) { + // Cache the Parker in the java.lang.Thread oop for next time. + java_lang_Thread::set_park_event(java_thread, addr_to_java(p)); } } } } - } + } // ThreadsListHandle is destroyed here. if (p != NULL) { HOTSPOT_THREAD_UNPARK((uintptr_t) p); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 84510d0da19..28d8851ff08 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -55,11 +55,15 @@ #include "runtime/os.hpp" #include "runtime/sweeper.hpp" #include "runtime/thread.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vm_version.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" +#if INCLUDE_CDS +#include "prims/cdsoffsets.hpp" +#endif // INCLUDE_CDS #if INCLUDE_ALL_GCS #include "gc/g1/concurrentMarkThread.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" @@ -665,7 +669,7 @@ class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation { int result() const { return _result; } void doit() { - for (JavaThread* t = Threads::first(); t != NULL; t = t->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { if (t->has_last_Java_frame()) { for (StackFrameStream fst(t, UseBiasedLocking); !fst.is_done(); fst.next()) { frame* f = fst.current(); @@ -1729,6 +1733,18 @@ WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env)) #endif WB_END + +#if INCLUDE_CDS + +WB_ENTRY(jint, WB_GetOffsetForName(JNIEnv* env, jobject o, jstring name)) + ResourceMark rm; + char* c_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name)); + int result = CDSOffsets::find_offset(c_name); + return (jint)result; +WB_END + +#endif // INCLUDE_CDS + WB_ENTRY(jint, WB_HandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_handle, jboolean all_threads)) class TraceSelfClosure : public ThreadClosure { jint _num_threads_completed; @@ -1917,6 +1933,9 @@ static JNINativeMethod methods[] = { {CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests}, {CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea}, {CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize}, +#if INCLUDE_CDS + {CC"getOffsetForName0", CC"(Ljava/lang/String;)I", (void*)&WB_GetOffsetForName}, +#endif #if INCLUDE_ALL_GCS {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, {CC"g1IsHumongous0", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous }, diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index de4adedf8f2..2540390b5c9 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -114,6 +114,108 @@ bool Arguments::_has_jimage = false; char* Arguments::_ext_dirs = NULL; +bool PathString::set_value(const char *value) { + if (_value != NULL) { + FreeHeap(_value); + } + _value = AllocateHeap(strlen(value)+1, mtArguments); + assert(_value != NULL, "Unable to allocate space for new path value"); + if (_value != NULL) { + strcpy(_value, value); + } else { + // not able to allocate + return false; + } + return true; +} + +void PathString::append_value(const char *value) { + char *sp; + size_t len = 0; + if (value != NULL) { + len = strlen(value); + if (_value != NULL) { + len += strlen(_value); + } + sp = AllocateHeap(len+2, mtArguments); + assert(sp != NULL, "Unable to allocate space for new append path value"); + if (sp != NULL) { + if (_value != NULL) { + strcpy(sp, _value); + strcat(sp, os::path_separator()); + strcat(sp, value); + FreeHeap(_value); + } else { + strcpy(sp, value); + } + _value = sp; + } + } +} + +PathString::PathString(const char* value) { + if (value == NULL) { + _value = NULL; + } else { + _value = AllocateHeap(strlen(value)+1, mtArguments); + strcpy(_value, value); + } +} + +PathString::~PathString() { + if (_value != NULL) { + FreeHeap(_value); + _value = NULL; + } +} + +ModulePatchPath::ModulePatchPath(const char* module_name, const char* path) { + assert(module_name != NULL && path != NULL, "Invalid module name or path value"); + size_t len = strlen(module_name) + 1; + _module_name = AllocateHeap(len, mtInternal); + strncpy(_module_name, module_name, len); // copy the trailing null + _path = new PathString(path); +} + +ModulePatchPath::~ModulePatchPath() { + if (_module_name != NULL) { + FreeHeap(_module_name); + _module_name = NULL; + } + if (_path != NULL) { + delete _path; + _path = NULL; + } +} + +SystemProperty::SystemProperty(const char* key, const char* value, bool writeable, bool internal) : PathString(value) { + if (key == NULL) { + _key = NULL; + } else { + _key = AllocateHeap(strlen(key)+1, mtArguments); + strcpy(_key, key); + } + _next = NULL; + _internal = internal; + _writeable = writeable; +} + +AgentLibrary::AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) { + _name = AllocateHeap(strlen(name)+1, mtArguments); + strcpy(_name, name); + if (options == NULL) { + _options = NULL; + } else { + _options = AllocateHeap(strlen(options)+1, mtArguments); + strcpy(_options, options); + } + _is_absolute_path = is_absolute_path; + _os_lib = os_lib; + _next = NULL; + _state = agent_invalid; + _is_static_lib = false; +} + // Check if head of 'option' matches 'name', and sets 'tail' to the remaining // part of the option string. static bool match_option(const JavaVMOption *option, const char* name, @@ -180,6 +282,23 @@ bool needs_module_property_warning = false; #define UPGRADE_PATH "upgrade.path" #define UPGRADE_PATH_LEN 12 +void Arguments::add_init_library(const char* name, char* options) { + _libraryList.add(new AgentLibrary(name, options, false, NULL)); +} + +void Arguments::add_init_agent(const char* name, char* options, bool absolute_path) { + _agentList.add(new AgentLibrary(name, options, absolute_path, NULL)); +} + +// Late-binding agents not started via arguments +void Arguments::add_loaded_agent(AgentLibrary *agentLib) { + _agentList.add(agentLib); +} + +void Arguments::add_loaded_agent(const char* name, char* options, bool absolute_path, void* os_lib) { + _agentList.add(new AgentLibrary(name, options, absolute_path, os_lib)); +} + // Return TRUE if option matches 'property', or 'property=', or 'property.'. static bool matches_property_suffix(const char* option, const char* property, size_t len) { return ((strncmp(option, property, len) == 0) && @@ -2152,12 +2271,7 @@ bool Arguments::check_vm_args_consistency() { // Check lower bounds of the code cache // Template Interpreter code is approximately 3X larger in debug builds. uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); - if (InitialCodeCacheSize < (uintx)os::vm_page_size()) { - jio_fprintf(defaultStream::error_stream(), - "Invalid InitialCodeCacheSize=%dK. Must be at least %dK.\n", InitialCodeCacheSize/K, - os::vm_page_size()/K); - status = false; - } else if (ReservedCodeCacheSize < InitialCodeCacheSize) { + if (ReservedCodeCacheSize < InitialCodeCacheSize) { jio_fprintf(defaultStream::error_stream(), "Invalid ReservedCodeCacheSize: %dK. Must be at least InitialCodeCacheSize=%dK.\n", ReservedCodeCacheSize/K, InitialCodeCacheSize/K); @@ -2212,7 +2326,27 @@ bool Arguments::check_vm_args_consistency() { } FLAG_SET_CMDLINE(bool, PostLoopMultiversioning, false); } + if (UseCountedLoopSafepoints && LoopStripMiningIter == 0) { + if (!FLAG_IS_DEFAULT(UseCountedLoopSafepoints) || !FLAG_IS_DEFAULT(LoopStripMiningIter)) { + warning("When counted loop safepoints are enabled, LoopStripMiningIter must be at least 1 (a safepoint every 1 iteration): setting it to 1"); + } + LoopStripMiningIter = 1; + } else if (!UseCountedLoopSafepoints && LoopStripMiningIter > 0) { + if (!FLAG_IS_DEFAULT(UseCountedLoopSafepoints) || !FLAG_IS_DEFAULT(LoopStripMiningIter)) { + warning("Disabling counted safepoints implies no loop strip mining: setting LoopStripMiningIter to 0"); + } + LoopStripMiningIter = 0; + } + if (FLAG_IS_DEFAULT(LoopStripMiningIterShortLoop)) { + // blind guess + LoopStripMiningIterShortLoop = LoopStripMiningIter / 10; + } #endif + if (!FLAG_IS_DEFAULT(AllocateHeapAt)) { + if ((UseNUMAInterleaving && !FLAG_IS_DEFAULT(UseNUMAInterleaving)) || (UseNUMA && !FLAG_IS_DEFAULT(UseNUMA))) { + log_warning(arguments) ("NUMA support for Heap depends on the file system when AllocateHeapAt option is used.\n"); + } + } return status; } @@ -2770,18 +2904,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m if (FLAG_SET_CMDLINE(intx, ThreadStackSize, value) != Flag::SUCCESS) { return JNI_EINVAL; } - } else if (match_option(option, "-XX:CodeCacheExpansionSize=", &tail)) { - julong long_CodeCacheExpansionSize = 0; - ArgsRange errcode = parse_memory_size(tail, &long_CodeCacheExpansionSize, os::vm_page_size()); - if (errcode != arg_in_range) { - jio_fprintf(defaultStream::error_stream(), - "Invalid argument: %s. Must be at least %luK.\n", option->optionString, - os::vm_page_size()/K); - return JNI_EINVAL; - } - if (FLAG_SET_CMDLINE(uintx, CodeCacheExpansionSize, (uintx)long_CodeCacheExpansionSize) != Flag::SUCCESS) { - return JNI_EINVAL; - } } else if (match_option(option, "-Xmaxjitcodesize", &tail) || match_option(option, "-XX:ReservedCodeCacheSize=", &tail)) { julong long_ReservedCodeCacheSize = 0; @@ -2795,45 +2917,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m if (FLAG_SET_CMDLINE(uintx, ReservedCodeCacheSize, (uintx)long_ReservedCodeCacheSize) != Flag::SUCCESS) { return JNI_EINVAL; } - // -XX:NonNMethodCodeHeapSize= - } else if (match_option(option, "-XX:NonNMethodCodeHeapSize=", &tail)) { - julong long_NonNMethodCodeHeapSize = 0; - - ArgsRange errcode = parse_memory_size(tail, &long_NonNMethodCodeHeapSize, 1); - if (errcode != arg_in_range) { - jio_fprintf(defaultStream::error_stream(), - "Invalid maximum non-nmethod code heap size: %s.\n", option->optionString); - return JNI_EINVAL; - } - if (FLAG_SET_CMDLINE(uintx, NonNMethodCodeHeapSize, (uintx)long_NonNMethodCodeHeapSize) != Flag::SUCCESS) { - return JNI_EINVAL; - } - // -XX:ProfiledCodeHeapSize= - } else if (match_option(option, "-XX:ProfiledCodeHeapSize=", &tail)) { - julong long_ProfiledCodeHeapSize = 0; - - ArgsRange errcode = parse_memory_size(tail, &long_ProfiledCodeHeapSize, 1); - if (errcode != arg_in_range) { - jio_fprintf(defaultStream::error_stream(), - "Invalid maximum profiled code heap size: %s.\n", option->optionString); - return JNI_EINVAL; - } - if (FLAG_SET_CMDLINE(uintx, ProfiledCodeHeapSize, (uintx)long_ProfiledCodeHeapSize) != Flag::SUCCESS) { - return JNI_EINVAL; - } - // -XX:NonProfiledCodeHeapSizee= - } else if (match_option(option, "-XX:NonProfiledCodeHeapSize=", &tail)) { - julong long_NonProfiledCodeHeapSize = 0; - - ArgsRange errcode = parse_memory_size(tail, &long_NonProfiledCodeHeapSize, 1); - if (errcode != arg_in_range) { - jio_fprintf(defaultStream::error_stream(), - "Invalid maximum non-profiled code heap size: %s.\n", option->optionString); - return JNI_EINVAL; - } - if (FLAG_SET_CMDLINE(uintx, NonProfiledCodeHeapSize, (uintx)long_NonProfiledCodeHeapSize) != Flag::SUCCESS) { - return JNI_EINVAL; - } // -green } else if (match_option(option, "-green")) { jio_fprintf(defaultStream::error_stream(), @@ -3936,6 +4019,14 @@ jint Arguments::match_special_option_and_act(const JavaVMInitArgs* args, vm_exit(0); } #endif + + if (match_option(option, "-XX:+UseAppCDS")) { + Flag* flag = Flag::find_flag("SharedArchiveFile", 17, true, true); + if (flag->is_diagnostic()) { + flag->clear_diagnostic(); + } + continue; + } } return JNI_OK; } @@ -4306,26 +4397,7 @@ jint Arguments::apply_ergo() { } #endif - bool aot_enabled = UseAOT && AOTLibrary != NULL; - bool jvmci_enabled = NOT_JVMCI(false) JVMCI_ONLY(EnableJVMCI || UseJVMCICompiler); - bool handshakes_supported = SafepointMechanism::supports_thread_local_poll() && !aot_enabled && !jvmci_enabled && ThreadLocalHandshakes; // ThreadLocalHandshakesConstraintFunc handles the constraints. - // Here we try to figure out if a mutual exclusive option have been set that conflict with a default. - if (handshakes_supported) { - FLAG_SET_DEFAULT(UseAOT, false); // Clear the AOT flag to make sure it doesn't try to initialize. - } else { - if (FLAG_IS_DEFAULT(ThreadLocalHandshakes) && ThreadLocalHandshakes) { - if (aot_enabled) { - // If user enabled AOT but ThreadLocalHandshakes is at default set it to false. - log_debug(ergo)("Disabling ThreadLocalHandshakes for UseAOT."); - FLAG_SET_DEFAULT(ThreadLocalHandshakes, false); - } else if (jvmci_enabled){ - // If user enabled JVMCI but ThreadLocalHandshakes is at default set it to false. - log_debug(ergo)("Disabling ThreadLocalHandshakes for EnableJVMCI/UseJVMCICompiler."); - FLAG_SET_DEFAULT(ThreadLocalHandshakes, false); - } - } - } if (FLAG_IS_DEFAULT(ThreadLocalHandshakes) || !SafepointMechanism::supports_thread_local_poll()) { log_debug(ergo)("ThreadLocalHandshakes %s", ThreadLocalHandshakes ? "enabled." : "disabled."); } else { @@ -4337,7 +4409,9 @@ jint Arguments::apply_ergo() { jint Arguments::adjust_after_os() { if (UseNUMA) { - if (UseParallelGC || UseParallelOldGC) { + if (!FLAG_IS_DEFAULT(AllocateHeapAt)) { + FLAG_SET_ERGO(bool, UseNUMA, false); + } else if (UseParallelGC || UseParallelOldGC) { if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) { FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M); } diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 43c0ff37d33..222f4b25ad6 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -27,6 +27,7 @@ #include "logging/logLevel.hpp" #include "logging/logTag.hpp" +#include "memory/allocation.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/perfData.hpp" @@ -59,60 +60,11 @@ class PathString : public CHeapObj { public: char* value() const { return _value; } - bool set_value(const char *value) { - if (_value != NULL) { - FreeHeap(_value); - } - _value = AllocateHeap(strlen(value)+1, mtArguments); - assert(_value != NULL, "Unable to allocate space for new path value"); - if (_value != NULL) { - strcpy(_value, value); - } else { - // not able to allocate - return false; - } - return true; - } + bool set_value(const char *value); + void append_value(const char *value); - void append_value(const char *value) { - char *sp; - size_t len = 0; - if (value != NULL) { - len = strlen(value); - if (_value != NULL) { - len += strlen(_value); - } - sp = AllocateHeap(len+2, mtArguments); - assert(sp != NULL, "Unable to allocate space for new append path value"); - if (sp != NULL) { - if (_value != NULL) { - strcpy(sp, _value); - strcat(sp, os::path_separator()); - strcat(sp, value); - FreeHeap(_value); - } else { - strcpy(sp, value); - } - _value = sp; - } - } - } - - PathString(const char* value) { - if (value == NULL) { - _value = NULL; - } else { - _value = AllocateHeap(strlen(value)+1, mtArguments); - strcpy(_value, value); - } - } - - ~PathString() { - if (_value != NULL) { - FreeHeap(_value); - _value = NULL; - } - } + PathString(const char* value); + ~PathString(); }; // ModulePatchPath records the module/path pair as specified to --patch-module. @@ -121,24 +73,8 @@ private: char* _module_name; PathString* _path; public: - ModulePatchPath(const char* module_name, const char* path) { - assert(module_name != NULL && path != NULL, "Invalid module name or path value"); - size_t len = strlen(module_name) + 1; - _module_name = AllocateHeap(len, mtInternal); - strncpy(_module_name, module_name, len); // copy the trailing null - _path = new PathString(path); - } - - ~ModulePatchPath() { - if (_module_name != NULL) { - FreeHeap(_module_name); - _module_name = NULL; - } - if (_path != NULL) { - delete _path; - _path = NULL; - } - } + ModulePatchPath(const char* module_name, const char* path); + ~ModulePatchPath(); inline void set_path(const char* path) { _path->set_value(path); } inline const char* module_name() const { return _module_name; } @@ -185,17 +121,7 @@ class SystemProperty : public PathString { } // Constructor - SystemProperty(const char* key, const char* value, bool writeable, bool internal = false) : PathString(value) { - if (key == NULL) { - _key = NULL; - } else { - _key = AllocateHeap(strlen(key)+1, mtArguments); - strcpy(_key, key); - } - _next = NULL; - _internal = internal; - _writeable = writeable; - } + SystemProperty(const char* key, const char* value, bool writeable, bool internal = false); }; @@ -234,21 +160,7 @@ public: void set_invalid() { _state = agent_invalid; } // Constructor - AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) { - _name = AllocateHeap(strlen(name)+1, mtArguments); - strcpy(_name, name); - if (options == NULL) { - _options = NULL; - } else { - _options = AllocateHeap(strlen(options)+1, mtArguments); - strcpy(_options, options); - } - _is_absolute_path = is_absolute_path; - _os_lib = os_lib; - _next = NULL; - _state = agent_invalid; - _is_static_lib = false; - } + AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib); }; // maintain an order of entry list of AgentLibrary @@ -420,19 +332,15 @@ class Arguments : AllStatic { // -Xrun arguments static AgentLibraryList _libraryList; - static void add_init_library(const char* name, char* options) - { _libraryList.add(new AgentLibrary(name, options, false, NULL)); } + static void add_init_library(const char* name, char* options); // -agentlib and -agentpath arguments static AgentLibraryList _agentList; - static void add_init_agent(const char* name, char* options, bool absolute_path) - { _agentList.add(new AgentLibrary(name, options, absolute_path, NULL)); } + static void add_init_agent(const char* name, char* options, bool absolute_path); // Late-binding agents not started via arguments - static void add_loaded_agent(AgentLibrary *agentLib) - { _agentList.add(agentLib); } - static void add_loaded_agent(const char* name, char* options, bool absolute_path, void* os_lib) - { _agentList.add(new AgentLibrary(name, options, absolute_path, os_lib)); } + static void add_loaded_agent(AgentLibrary *agentLib); + static void add_loaded_agent(const char* name, char* options, bool absolute_path, void* os_lib); // Operation modi static Mode _mode; diff --git a/src/hotspot/share/runtime/arguments_ext.hpp b/src/hotspot/share/runtime/arguments_ext.hpp index d1c9f183e8e..3ae21e1267f 100644 --- a/src/hotspot/share/runtime/arguments_ext.hpp +++ b/src/hotspot/share/runtime/arguments_ext.hpp @@ -36,7 +36,6 @@ public: // Otherwise returns false. static inline bool process_options(const JavaVMOption *option) { return false; } static inline void report_unsupported_options() { } - static inline bool using_AppCDS() { return false; } }; void ArgumentsExt::set_gc_specific_flags() { diff --git a/src/hotspot/share/runtime/biasedLocking.cpp b/src/hotspot/share/runtime/biasedLocking.cpp index de93a4b370a..a1e70a97478 100644 --- a/src/hotspot/share/runtime/biasedLocking.cpp +++ b/src/hotspot/share/runtime/biasedLocking.cpp @@ -32,6 +32,7 @@ #include "runtime/basicLock.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/task.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" @@ -214,12 +215,8 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ if (requesting_thread == biased_thread) { thread_is_alive = true; } else { - for (JavaThread* cur_thread = Threads::first(); cur_thread != NULL; cur_thread = cur_thread->next()) { - if (cur_thread == biased_thread) { - thread_is_alive = true; - break; - } - } + ThreadsListHandle tlh; + thread_is_alive = tlh.includes(biased_thread); } if (!thread_is_alive) { if (allow_rebias) { @@ -390,72 +387,76 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, Klass* k_o = o->klass(); Klass* klass = k_o; - if (bulk_rebias) { - // Use the epoch in the klass of the object to implicitly revoke - // all biases of objects of this data type and force them to be - // reacquired. However, we also need to walk the stacks of all - // threads and update the headers of lightweight locked objects - // with biases to have the current epoch. + { + JavaThreadIteratorWithHandle jtiwh; - // If the prototype header doesn't have the bias pattern, don't - // try to update the epoch -- assume another VM operation came in - // and reset the header to the unbiased state, which will - // implicitly cause all existing biases to be revoked - if (klass->prototype_header()->has_bias_pattern()) { - int prev_epoch = klass->prototype_header()->bias_epoch(); - klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch()); - int cur_epoch = klass->prototype_header()->bias_epoch(); + if (bulk_rebias) { + // Use the epoch in the klass of the object to implicitly revoke + // all biases of objects of this data type and force them to be + // reacquired. However, we also need to walk the stacks of all + // threads and update the headers of lightweight locked objects + // with biases to have the current epoch. - // Now walk all threads' stacks and adjust epochs of any biased - // and locked objects of this data type we encounter - for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) { + // If the prototype header doesn't have the bias pattern, don't + // try to update the epoch -- assume another VM operation came in + // and reset the header to the unbiased state, which will + // implicitly cause all existing biases to be revoked + if (klass->prototype_header()->has_bias_pattern()) { + int prev_epoch = klass->prototype_header()->bias_epoch(); + klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch()); + int cur_epoch = klass->prototype_header()->bias_epoch(); + + // Now walk all threads' stacks and adjust epochs of any biased + // and locked objects of this data type we encounter + for (; JavaThread *thr = jtiwh.next(); ) { + GrowableArray* cached_monitor_info = get_or_compute_monitor_info(thr); + for (int i = 0; i < cached_monitor_info->length(); i++) { + MonitorInfo* mon_info = cached_monitor_info->at(i); + oop owner = mon_info->owner(); + markOop mark = owner->mark(); + if ((owner->klass() == k_o) && mark->has_bias_pattern()) { + // We might have encountered this object already in the case of recursive locking + assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment"); + owner->set_mark(mark->set_bias_epoch(cur_epoch)); + } + } + } + } + + // At this point we're done. All we have to do is potentially + // adjust the header of the given object to revoke its bias. + revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL); + } else { + if (log_is_enabled(Info, biasedlocking)) { + ResourceMark rm; + log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); + } + + // Disable biased locking for this data type. Not only will this + // cause future instances to not be biased, but existing biased + // instances will notice that this implicitly caused their biases + // to be revoked. + klass->set_prototype_header(markOopDesc::prototype()); + + // Now walk all threads' stacks and forcibly revoke the biases of + // any locked and biased objects of this data type we encounter. + for (; JavaThread *thr = jtiwh.next(); ) { GrowableArray* cached_monitor_info = get_or_compute_monitor_info(thr); for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); oop owner = mon_info->owner(); markOop mark = owner->mark(); if ((owner->klass() == k_o) && mark->has_bias_pattern()) { - // We might have encountered this object already in the case of recursive locking - assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment"); - owner->set_mark(mark->set_bias_epoch(cur_epoch)); + revoke_bias(owner, false, true, requesting_thread, NULL); } } } + + // Must force the bias of the passed object to be forcibly revoked + // as well to ensure guarantees to callers + revoke_bias(o, false, true, requesting_thread, NULL); } - - // At this point we're done. All we have to do is potentially - // adjust the header of the given object to revoke its bias. - revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL); - } else { - if (log_is_enabled(Info, biasedlocking)) { - ResourceMark rm; - log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); - } - - // Disable biased locking for this data type. Not only will this - // cause future instances to not be biased, but existing biased - // instances will notice that this implicitly caused their biases - // to be revoked. - klass->set_prototype_header(markOopDesc::prototype()); - - // Now walk all threads' stacks and forcibly revoke the biases of - // any locked and biased objects of this data type we encounter. - for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) { - GrowableArray* cached_monitor_info = get_or_compute_monitor_info(thr); - for (int i = 0; i < cached_monitor_info->length(); i++) { - MonitorInfo* mon_info = cached_monitor_info->at(i); - oop owner = mon_info->owner(); - markOop mark = owner->mark(); - if ((owner->klass() == k_o) && mark->has_bias_pattern()) { - revoke_bias(owner, false, true, requesting_thread, NULL); - } - } - } - - // Must force the bias of the passed object to be forcibly revoked - // as well to ensure guarantees to callers - revoke_bias(o, false, true, requesting_thread, NULL); - } + } // ThreadsListHandle is destroyed here. log_info(biasedlocking)("* Ending bulk revocation"); @@ -481,7 +482,7 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, static void clean_up_cached_monitor_info() { // Walk the thread list clearing out the cached monitors - for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { thr->set_cached_monitor_info(NULL); } } @@ -768,7 +769,7 @@ void BiasedLocking::preserve_marks() { ResourceMark rm; Thread* cur = Thread::current(); - for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { if (thread->has_last_Java_frame()) { RegisterMap rm(thread); for (javaVFrame* vf = thread->last_java_vframe(&rm); vf != NULL; vf = vf->java_sender()) { diff --git a/src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.cpp index 9df5d2bbec8..55483983094 100644 --- a/src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.cpp @@ -138,10 +138,6 @@ Flag::Error ThreadLocalHandshakesConstraintFunc(bool value, bool verbose) { CommandLineError::print(verbose, "ThreadLocalHandshakes not yet supported on this platform\n"); return Flag::VIOLATES_CONSTRAINT; } - if (UseAOT JVMCI_ONLY(|| EnableJVMCI || UseJVMCICompiler)) { - CommandLineError::print(verbose, "ThreadLocalHandshakes not yet supported in combination with AOT or JVMCI\n"); - return Flag::VIOLATES_CONSTRAINT; - } } return Flag::SUCCESS; } diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index fb93fbdd712..c61f41d2933 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -50,6 +50,7 @@ #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vframeArray.hpp" #include "runtime/vframe_hp.hpp" @@ -1297,7 +1298,7 @@ void Deoptimization::revoke_biases_of_monitors(CodeBlob* cb) { assert(SafepointSynchronize::is_at_safepoint(), "must only be called from safepoint"); GrowableArray* objects_to_revoke = new GrowableArray(); - for (JavaThread* jt = Threads::first(); jt != NULL ; jt = jt->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { if (jt->has_last_Java_frame()) { StackFrameStream sfs(jt, true); while (!sfs.is_done()) { diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index bdf69c29da6..ad4b27a3b0b 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -917,9 +917,6 @@ public: notproduct(bool, ZapVMHandleArea, trueInDebug, \ "Zap freed VM handle space with 0xBCBCBCBC") \ \ - develop(bool, ZapJNIHandleArea, trueInDebug, \ - "Zap freed JNI handle space with 0xFEFEFEFE") \ - \ notproduct(bool, ZapStackSegments, trueInDebug, \ "Zap allocated/freed stack segments with 0xFADFADED") \ \ @@ -2271,6 +2268,10 @@ public: diagnostic(bool, VerifyDuringGC, false, \ "Verify memory system during GC (between phases)") \ \ + diagnostic(ccstrlist, VerifyGCType, "", \ + "GC type(s) to verify when Verify*GC is enabled." \ + "Available types are collector specific.") \ + \ diagnostic(ccstrlist, VerifySubSet, "", \ "Memory sub-systems to verify when Verify*GC flag(s) " \ "are enabled. One or more sub-systems can be specified " \ @@ -2484,6 +2485,12 @@ public: LP64_ONLY(range(-1, max_intx/MICROUNITS)) \ NOT_LP64(range(-1, max_intx)) \ \ + diagnostic(bool, EnableThreadSMRExtraValidityChecks, true, \ + "Enable Thread SMR extra validity checks") \ + \ + diagnostic(bool, EnableThreadSMRStatistics, trueInDebug, \ + "Enable Thread SMR Statistics") \ + \ product(bool, Inline, true, \ "Enable inlining") \ \ @@ -3359,7 +3366,7 @@ public: \ product_pd(uintx, InitialCodeCacheSize, \ "Initial code cache size (in bytes)") \ - range(0, max_uintx) \ + range(os::vm_page_size(), max_uintx) \ \ develop_pd(uintx, CodeCacheMinimumUseSpace, \ "Minimum code cache size (in bytes) required to start VM.") \ @@ -3370,7 +3377,7 @@ public: \ product_pd(uintx, ReservedCodeCacheSize, \ "Reserved code cache size (in bytes) - maximum code cache size") \ - range(0, max_uintx) \ + range(os::vm_page_size(), max_uintx) \ \ product_pd(uintx, NonProfiledCodeHeapSize, \ "Size of code heap with non-profiled methods (in bytes)") \ @@ -3382,11 +3389,11 @@ public: \ product_pd(uintx, NonNMethodCodeHeapSize, \ "Size of code heap with non-nmethods (in bytes)") \ - range(0, max_uintx) \ + range(os::vm_page_size(), max_uintx) \ \ product_pd(uintx, CodeCacheExpansionSize, \ "Code cache expansion size (in bytes)") \ - range(0, max_uintx) \ + range(32*K, max_uintx) \ \ diagnostic_pd(uintx, CodeCacheMinBlockLength, \ "Minimum number of segments in a code cache block") \ @@ -3926,6 +3933,13 @@ public: "Address to allocate shared memory region for class data") \ range(0, SIZE_MAX) \ \ + product(bool, UseAppCDS, false, \ + "Enable Application Class Data Sharing when using shared spaces") \ + writeable(CommandLineOnly) \ + \ + product(ccstr, SharedArchiveConfigFile, NULL, \ + "Data to add to the CDS archive file") \ + \ product(uintx, SharedSymbolTableBucketSize, 4, \ "Average number of symbols per bucket in shared table") \ range(2, 246) \ @@ -4073,7 +4087,11 @@ public: diagnostic(bool, CompilerDirectivesPrint, false, \ "Print compiler directives on installation.") \ diagnostic(int, CompilerDirectivesLimit, 50, \ - "Limit on number of compiler directives.") + "Limit on number of compiler directives.") \ + \ + product(ccstr, AllocateHeapAt, NULL, \ + "Path to the directoy where a temporary file will be created " \ + "to use as the backing store for Java Heap.") /* diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp index f81c235c13d..0b816b25ed3 100644 --- a/src/hotspot/share/runtime/handshake.cpp +++ b/src/hotspot/share/runtime/handshake.cpp @@ -37,8 +37,6 @@ #include "utilities/formatBuffer.hpp" #include "utilities/preserveException.hpp" -#define ALL_JAVA_THREADS(X) for (JavaThread* X = Threads::first(); X; X = X->next()) - class HandshakeOperation: public StackObj { public: virtual void do_handshake(JavaThread* thread) = 0; @@ -94,8 +92,7 @@ bool VM_Handshake::handshake_has_timed_out(jlong start_time) { void VM_Handshake::handle_timeout() { LogStreamHandle(Warning, handshake) log_stream; - MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); - ALL_JAVA_THREADS(thr) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { if (thr->has_handshake()) { log_stream.print("Thread " PTR_FORMAT " has not cleared its handshake op", p2i(thr)); thr->print_thread_state_on(&log_stream); @@ -117,8 +114,8 @@ class VM_HandshakeOneThread: public VM_Handshake { TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); { - MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); - if (Threads::includes(_target)) { + ThreadsListHandle tlh; + if (tlh.includes(_target)) { set_handshake(_target); _thread_alive = true; } @@ -139,9 +136,24 @@ class VM_HandshakeOneThread: public VM_Handshake { handle_timeout(); } + // We need to re-think this with SMR ThreadsList. + // There is an assumption in the code that the Threads_lock should be + // locked during certain phases. MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); - _target->handshake_process_by_vmthread(); - + ThreadsListHandle tlh; + if (tlh.includes(_target)) { + // Warning _target's address might be re-used. + // handshake_process_by_vmthread will check the semaphore for us again. + // Since we can't have more then one handshake in flight a reuse of + // _target's address should be okay since the new thread will not have + // an operation. + _target->handshake_process_by_vmthread(); + } else { + // We can't warn here since the thread does cancel_handshake after + // it has been removed from the ThreadsList. So we should just keep + // looping here until while below returns false. If we have a bug, + // then we hang here, which is good for debugging. + } } while (!poll_for_completed_thread()); } @@ -157,15 +169,15 @@ class VM_HandshakeAllThreads: public VM_Handshake { void doit() { TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); - int number_of_threads_issued = -1; - int number_of_threads_completed = 0; - { - MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); - number_of_threads_issued = Threads::number_of_threads(); + int number_of_threads_issued = 0; + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { + set_handshake(thr); + number_of_threads_issued++; + } - ALL_JAVA_THREADS(thr) { - set_handshake(thr); - } + if (number_of_threads_issued < 1) { + log_debug(handshake)("No threads to handshake."); + return; } if (!UseMembar) { @@ -174,6 +186,7 @@ class VM_HandshakeAllThreads: public VM_Handshake { log_debug(handshake)("Threads signaled, begin processing blocked threads by VMThtread"); const jlong start_time = os::elapsed_counter(); + int number_of_threads_completed = 0; do { // Check if handshake operation has timed out if (handshake_has_timed_out(start_time)) { @@ -184,13 +197,19 @@ class VM_HandshakeAllThreads: public VM_Handshake { // Observing a blocked state may of course be transient but the processing is guarded // by semaphores and we optimistically begin by working on the blocked threads { + // We need to re-think this with SMR ThreadsList. + // There is an assumption in the code that the Threads_lock should + // be locked during certain phases. MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); - ALL_JAVA_THREADS(thr) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { + // A new thread on the ThreadsList will not have an operation, + // hence it is skipped in handshake_process_by_vmthread. thr->handshake_process_by_vmthread(); } } while (poll_for_completed_thread()) { + // Includes canceled operations by exiting threads. number_of_threads_completed++; } @@ -212,7 +231,7 @@ public: _thread_cl(cl), _target_thread(target), _all_threads(false), _thread_alive(false) {} void doit() { - ALL_JAVA_THREADS(t) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { if (_all_threads || t == _target_thread) { if (t == _target_thread) { _thread_alive = true; @@ -298,8 +317,8 @@ void HandshakeState::cancel_inner(JavaThread* thread) { assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); #ifdef DEBUG { - MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); - assert(!Threads::includes(thread), "java thread must not be on threads list"); + ThreadsListHandle tlh; + assert(!tlh.includes(_target), "java thread must not be on threads list"); } #endif HandshakeOperation* op = _operation; diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 11d84f00ee8..9c19095f142 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -356,6 +356,8 @@ void print_statistics() { if (PrintNMTStatistics) { MemTracker::final_report(tty); } + + Threads::log_smr_statistics(); } #else // PRODUCT MODE STATISTICS @@ -396,6 +398,8 @@ void print_statistics() { if (LogTouchedMethods && PrintTouchedMethodsAtExit) { Method::print_touched_methods(tty); } + + Threads::log_smr_statistics(); } #endif diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp index 8819f3c2cfc..483f9a5cb6e 100644 --- a/src/hotspot/share/runtime/jniHandles.cpp +++ b/src/hotspot/share/runtime/jniHandles.cpp @@ -279,13 +279,15 @@ JNIHandleBlock* JNIHandleBlock::_block_list = NULL; #endif +#ifdef ASSERT void JNIHandleBlock::zap() { // Zap block values _top = 0; for (int index = 0; index < block_size_in_oops; index++) { - _handles[index] = badJNIHandle; + _handles[index] = NULL; } } +#endif // ASSERT JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) { assert(thread == NULL || thread == Thread::current(), "sanity check"); @@ -307,7 +309,7 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) { // Allocate new block block = new JNIHandleBlock(); _blocks_allocated++; - if (ZapJNIHandleArea) block->zap(); + block->zap(); #ifndef PRODUCT // Link new block to list of all allocated blocks block->_block_list_link = _block_list; @@ -339,7 +341,7 @@ void JNIHandleBlock::release_block(JNIHandleBlock* block, Thread* thread) { // we _don't_ want the block to be kept on the free_handle_block. // See for instance JavaThread::exit(). if (thread != NULL ) { - if (ZapJNIHandleArea) block->zap(); + block->zap(); JNIHandleBlock* freelist = thread->free_handle_block(); block->_pop_frame_link = NULL; thread->set_free_handle_block(block); @@ -360,7 +362,7 @@ void JNIHandleBlock::release_block(JNIHandleBlock* block, Thread* thread) { MutexLockerEx ml(JNIHandleBlockFreeList_lock, Mutex::_no_safepoint_check_flag); while (block != NULL) { - if (ZapJNIHandleArea) block->zap(); + block->zap(); JNIHandleBlock* next = block->_next; block->_next = _block_free_list; _block_free_list = block; @@ -453,13 +455,13 @@ jobject JNIHandleBlock::allocate_handle(oop obj) { break; } current->_top = 0; - if (ZapJNIHandleArea) current->zap(); + current->zap(); } // Clear initial block _free_list = NULL; _allocate_before_rebuild = 0; _last = this; - if (ZapJNIHandleArea) zap(); + zap(); } // Try last block diff --git a/src/hotspot/share/runtime/jniHandles.hpp b/src/hotspot/share/runtime/jniHandles.hpp index b7cd7668549..8bba3e3125b 100644 --- a/src/hotspot/share/runtime/jniHandles.hpp +++ b/src/hotspot/share/runtime/jniHandles.hpp @@ -148,7 +148,7 @@ class JNIHandleBlock : public CHeapObj { static int _blocks_allocated; // For debugging/printing // Fill block with bad_handle values - void zap(); + void zap() NOT_DEBUG_RETURN; // Free list computation void rebuild_free_list(); @@ -219,9 +219,8 @@ inline oop& JNIHandles::jweak_ref(jobject handle) { template inline oop JNIHandles::guard_value(oop value) { if (!external_guard) { - assert(value != badJNIHandle, "Pointing to zapped jni handle area"); assert(value != deleted_handle(), "Used a deleted global handle"); - } else if ((value == badJNIHandle) || (value == deleted_handle())) { + } else if (value == deleted_handle()) { value = NULL; } return value; diff --git a/src/hotspot/share/runtime/memprofiler.cpp b/src/hotspot/share/runtime/memprofiler.cpp index 77a1f183daa..396285ac8c8 100644 --- a/src/hotspot/share/runtime/memprofiler.cpp +++ b/src/hotspot/share/runtime/memprofiler.cpp @@ -36,6 +36,7 @@ #include "runtime/os.hpp" #include "runtime/task.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vmThread.hpp" #ifndef PRODUCT @@ -51,8 +52,6 @@ class MemProfilerTask : public PeriodicTask { void MemProfilerTask::task() { - // Get thread lock to provide mutual exclusion, and so we can iterate safely over the thread list. - MutexLocker mu(Threads_lock); MemProfiler::do_trace(); } @@ -109,20 +108,21 @@ void MemProfiler::do_trace() { // Calculate thread local sizes size_t handles_memory_usage = VMThread::vm_thread()->handle_area()->size_in_bytes(); size_t resource_memory_usage = VMThread::vm_thread()->resource_area()->size_in_bytes(); - JavaThread *cur = Threads::first(); - while (cur != NULL) { - handles_memory_usage += cur->handle_area()->size_in_bytes(); - resource_memory_usage += cur->resource_area()->size_in_bytes(); - cur = cur->next(); - } + { + JavaThreadIteratorWithHandle jtiwh; + for (; JavaThread *cur = jtiwh.next(); ) { + handles_memory_usage += cur->handle_area()->size_in_bytes(); + resource_memory_usage += cur->resource_area()->size_in_bytes(); + } - // Print trace line in log - fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",", - os::elapsedTime(), - Threads::number_of_threads(), - InstanceKlass::number_of_instance_classes(), - Universe::heap()->used() / K, - Universe::heap()->capacity() / K); + // Print trace line in log + fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",", + os::elapsedTime(), + jtiwh.length(), + InstanceKlass::number_of_instance_classes(), + Universe::heap()->used() / K, + Universe::heap()->capacity() / K); + } fprintf(_log_fp, UINTX_FORMAT_W(6) ",", CodeCache::capacity() / K); diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 40037a496a5..7f659bfecb1 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/markOop.hpp" #include "oops/oop.inline.hpp" @@ -242,6 +243,19 @@ static volatile int InitDone = 0; // * See also http://blogs.sun.com/dave +void* ObjectMonitor::operator new (size_t size) throw() { + return AllocateHeap(size, mtInternal); +} +void* ObjectMonitor::operator new[] (size_t size) throw() { + return operator new (size); +} +void ObjectMonitor::operator delete(void* p) { + FreeHeap(p); +} +void ObjectMonitor::operator delete[] (void *p) { + operator delete(p); +} + // ----------------------------------------------------------------------------- // Enter support @@ -2138,6 +2152,7 @@ ObjectWaiter::ObjectWaiter(Thread* thread) { _next = NULL; _prev = NULL; _notified = 0; + _notifier_tid = 0; TState = TS_RUN; _thread = thread; _event = thread->_ParkEvent; diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 484b99aa2da..ee610b1a4db 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_RUNTIME_OBJECTMONITOR_HPP #define SHARE_VM_RUNTIME_OBJECTMONITOR_HPP +#include "memory/allocation.hpp" #include "memory/padded.hpp" #include "runtime/os.hpp" #include "runtime/park.hpp" @@ -212,18 +213,10 @@ class ObjectMonitor { static int Knob_VerifyMatch; static int Knob_SpinLimit; - void* operator new (size_t size) throw() { - return AllocateHeap(size, mtInternal); - } - void* operator new[] (size_t size) throw() { - return operator new (size); - } - void operator delete(void* p) { - FreeHeap(p); - } - void operator delete[] (void *p) { - operator delete(p); - } + void* operator new (size_t size) throw(); + void* operator new[] (size_t size) throw(); + void operator delete(void* p); + void operator delete[] (void *p); // TODO-FIXME: the "offset" routines should return a type of off_t instead of int ... // ByteSize would also be an appropriate type. diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 0306faa5515..dce176a8a52 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -54,6 +54,7 @@ #include "runtime/os.inline.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vm_version.hpp" #include "services/attachListener.hpp" #include "services/mallocTracker.hpp" @@ -197,15 +198,7 @@ char* os::iso8601_time(char* buffer, size_t buffer_length, bool utc) { } OSReturn os::set_priority(Thread* thread, ThreadPriority p) { -#ifdef ASSERT - if (!(!thread->is_Java_thread() || - Thread::current() == thread || - Threads_lock->owned_by_self() - || thread->is_Compiler_thread() - )) { - assert(false, "possibility of dangling Thread pointer"); - } -#endif + debug_only(Thread::check_for_dangling_thread_pointer(thread);) if (p >= MinPriority && p <= MaxPriority) { int priority = java_to_os_priority[p]; @@ -1100,7 +1093,7 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { } #endif - for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { // Check for privilege stack if (thread->privileged_stack_top() != NULL && thread->privileged_stack_top()->contains(addr)) { @@ -1126,7 +1119,6 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { if (verbose) thread->print_on(st); return; } - } // Check if in metaspace and print types that have vptrs (only method now) @@ -1665,7 +1657,6 @@ void os::initialize_initial_active_processor_count() { } void os::SuspendedThreadTask::run() { - assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this"); internal_do_task(); _done = true; } @@ -1674,10 +1665,21 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) { return os::pd_create_stack_guard_pages(addr, bytes); } -char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { - char* result = pd_reserve_memory(bytes, addr, alignment_hint); - if (result != NULL) { - MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); +char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, int file_desc) { + char* result = NULL; + + if (file_desc != -1) { + // Could have called pd_reserve_memory() followed by replace_existing_mapping_with_file_mapping(), + // but AIX may use SHM in which case its more trouble to detach the segment and remap memory to the file. + result = os::map_memory_to_file(addr, bytes, file_desc); + if (result != NULL) { + MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); + } + } else { + result = pd_reserve_memory(bytes, addr, alignment_hint); + if (result != NULL) { + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); + } } return result; @@ -1694,10 +1696,18 @@ char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, return result; } -char* os::attempt_reserve_memory_at(size_t bytes, char* addr) { - char* result = pd_attempt_reserve_memory_at(bytes, addr); - if (result != NULL) { - MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); +char* os::attempt_reserve_memory_at(size_t bytes, char* addr, int file_desc) { + char* result = NULL; + if (file_desc != -1) { + result = pd_attempt_reserve_memory_at(bytes, addr, file_desc); + if (result != NULL) { + MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); + } + } else { + result = pd_attempt_reserve_memory_at(bytes, addr); + if (result != NULL) { + MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); + } } return result; } diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 61999125339..83b24f574ed 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -108,8 +108,9 @@ class os: AllStatic { } static char* pd_reserve_memory(size_t bytes, char* addr = 0, - size_t alignment_hint = 0); + size_t alignment_hint = 0); static char* pd_attempt_reserve_memory_at(size_t bytes, char* addr); + static char* pd_attempt_reserve_memory_at(size_t bytes, char* addr, int file_desc); static void pd_split_reserved_memory(char *base, size_t size, size_t split, bool realloc); static bool pd_commit_memory(char* addr, size_t bytes, bool executable); @@ -310,11 +311,11 @@ class os: AllStatic { static int vm_allocation_granularity(); static char* reserve_memory(size_t bytes, char* addr = 0, - size_t alignment_hint = 0); + size_t alignment_hint = 0, int file_desc = -1); static char* reserve_memory(size_t bytes, char* addr, size_t alignment_hint, MEMFLAGS flags); - static char* reserve_memory_aligned(size_t size, size_t alignment); - static char* attempt_reserve_memory_at(size_t bytes, char* addr); + static char* reserve_memory_aligned(size_t size, size_t alignment, int file_desc = -1); + static char* attempt_reserve_memory_at(size_t bytes, char* addr, int file_desc = -1); static void split_reserved_memory(char *base, size_t size, size_t split, bool realloc); static bool commit_memory(char* addr, size_t bytes, bool executable); @@ -345,6 +346,14 @@ class os: AllStatic { static bool create_stack_guard_pages(char* addr, size_t bytes); static bool pd_create_stack_guard_pages(char* addr, size_t bytes); static bool remove_stack_guard_pages(char* addr, size_t bytes); + // Helper function to create a new file with template jvmheap.XXXXXX. + // Returns a valid fd on success or else returns -1 + static int create_file_for_heap(const char* dir); + // Map memory to the file referred by fd. This function is slightly different from map_memory() + // and is added to be used for implementation of -XX:AllocateHeapAt + static char* map_memory_to_file(char* base, size_t size, int fd); + // Replace existing reserved memory with file mapping + static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd); static char* map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only = false, diff --git a/src/hotspot/share/runtime/park.cpp b/src/hotspot/share/runtime/park.cpp index 6f278dff23a..6314b54bd64 100644 --- a/src/hotspot/share/runtime/park.cpp +++ b/src/hotspot/share/runtime/park.cpp @@ -23,10 +23,9 @@ */ #include "precompiled.hpp" +#include "memory/allocation.inline.hpp" #include "runtime/thread.hpp" - - // Lifecycle management for TSM ParkEvents. // ParkEvents are type-stable (TSM). // In our particular implementation they happen to be immortal. diff --git a/src/hotspot/share/runtime/perfData.cpp b/src/hotspot/share/runtime/perfData.cpp index d79bbc66b48..e6a9045825b 100644 --- a/src/hotspot/share/runtime/perfData.cpp +++ b/src/hotspot/share/runtime/perfData.cpp @@ -32,7 +32,7 @@ #include "runtime/mutex.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" -#include "runtime/perfData.hpp" +#include "runtime/perfData.inline.hpp" #include "utilities/exceptions.hpp" #include "utilities/globalDefinitions.hpp" @@ -611,3 +611,10 @@ PerfDataList* PerfDataList::clone() { return copy; } + +PerfTraceTime::~PerfTraceTime() { + if (!UsePerfData || (_recursion_counter != NULL && + --(*_recursion_counter) > 0)) return; + _t.stop(); + _timerp->inc(_t.ticks()); +} diff --git a/src/hotspot/share/runtime/perfData.hpp b/src/hotspot/share/runtime/perfData.hpp index 8fa9f14d598..f667ecc9d03 100644 --- a/src/hotspot/share/runtime/perfData.hpp +++ b/src/hotspot/share/runtime/perfData.hpp @@ -25,10 +25,11 @@ #ifndef SHARE_VM_RUNTIME_PERFDATA_HPP #define SHARE_VM_RUNTIME_PERFDATA_HPP -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "runtime/perfMemory.hpp" #include "runtime/timer.hpp" -#include "utilities/growableArray.hpp" + +template class GrowableArray; /* jvmstat global and subsystem counter name space - enumeration value * serve as an index into the PerfDataManager::_name_space[] array @@ -244,6 +245,7 @@ class PerfData : public CHeapObj { friend class StatSampler; // for access to protected void sample() friend class PerfDataManager; // for access to protected destructor + friend class VMStructs; public: @@ -629,10 +631,10 @@ class PerfDataList : public CHeapObj { bool contains(const char* name) { return find_by_name(name) != NULL; } // return the number of PerfData items in this list - int length() { return _set->length(); } + inline int length(); // add a PerfData item to this list - void append(PerfData *p) { _set->append(p); } + inline void append(PerfData *p); // remove the given PerfData item from this list. When called // while iterating over the list, this method will result in a @@ -640,7 +642,7 @@ class PerfDataList : public CHeapObj { // method is also impacted by this method as elements with an // index greater than the index of the element removed by this // method will be shifted down by one. - void remove(PerfData *p) { _set->remove(p); } + inline void remove(PerfData *p); // create a new PerfDataList from this list. The new list is // a shallow copy of the original list and care should be taken @@ -651,7 +653,7 @@ class PerfDataList : public CHeapObj { // for backward compatibility with GrowableArray - need to implement // some form of iterator to provide a cleaner abstraction for // iteration over the container. - PerfData* at(int index) { return _set->at(index); } + inline PerfData* at(int index); }; @@ -677,23 +679,23 @@ class PerfDataManager : AllStatic { protected: // return the list of all known PerfData items static PerfDataList* all(); - static int count() { return _all->length(); } + static inline int count(); // return the list of all known PerfData items that are to be // sampled by the StatSampler. static PerfDataList* sampled(); - static int sampled_count() { return _sampled->length(); } + static inline int sampled_count(); // return the list of all known PerfData items that have a // variability classification of type Constant static PerfDataList* constants(); - static int constants_count() { return _constants->length(); } + static inline int constants_count(); public: // method to check for the existence of a PerfData item with // the given name. - static bool exists(const char* name) { return _all->contains(name); } + static inline bool exists(const char* name); // method to search for a instrumentation object by name static PerfData* find_by_name(const char* name); @@ -929,12 +931,7 @@ class PerfTraceTime : public StackObj { inline void suspend() { if (!UsePerfData) return; _t.stop(); } inline void resume() { if (!UsePerfData) return; _t.start(); } - inline ~PerfTraceTime() { - if (!UsePerfData || (_recursion_counter != NULL && - --(*_recursion_counter) > 0)) return; - _t.stop(); - _timerp->inc(_t.ticks()); - } + ~PerfTraceTime(); }; /* The PerfTraceTimedEvent class is responsible for counting the diff --git a/src/hotspot/share/runtime/perfData.inline.hpp b/src/hotspot/share/runtime/perfData.inline.hpp new file mode 100644 index 00000000000..b867bbdbb4e --- /dev/null +++ b/src/hotspot/share/runtime/perfData.inline.hpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2017, 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_VM_RUNTIME_PERFDATA_INLINE_HPP +#define SHARE_VM_RUNTIME_PERFDATA_INLINE_HPP + +#include "runtime/perfData.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/growableArray.hpp" + +inline int PerfDataList::length() { + return _set->length(); +} + +inline void PerfDataList::append(PerfData *p) { + _set->append(p); +} + +inline void PerfDataList::remove(PerfData *p) { + _set->remove(p); +} + +inline PerfData* PerfDataList::at(int index) { + return _set->at(index); +} + +inline int PerfDataManager::count() { + return _all->length(); +} + +inline int PerfDataManager::sampled_count() { + return _sampled->length(); +} + +inline int PerfDataManager::constants_count() { + return _constants->length(); +} + +inline bool PerfDataManager::exists(const char* name) { + return _all->contains(name); +} + +#endif // SHARE_VM_RUNTIME_PERFDATA_INLINE_HPP diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp index 291ee50b170..23d56c8e0d5 100644 --- a/src/hotspot/share/runtime/safepoint.cpp +++ b/src/hotspot/share/runtime/safepoint.cpp @@ -59,6 +59,7 @@ #include "runtime/sweeper.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/timerTrace.hpp" #include "services/runtimeService.hpp" #include "trace/tracing.hpp" @@ -174,7 +175,7 @@ void SafepointSynchronize::begin() { if (SafepointMechanism::uses_thread_local_poll()) { // Arming the per thread poll while having _state != _not_synchronized means safepointing log_trace(safepoint)("Setting thread local yield flag for threads"); - for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) { // Make sure the threads start polling, it is time to yield. SafepointMechanism::arm_local_poll(cur); // release store, global state -> local state } @@ -200,133 +201,137 @@ void SafepointSynchronize::begin() { // Consider using active_processor_count() ... but that call is expensive. int ncpus = os::processor_count() ; + unsigned int iterations = 0; + { + JavaThreadIteratorWithHandle jtiwh; #ifdef ASSERT - for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) { - assert(cur->safepoint_state()->is_running(), "Illegal initial state"); - // Clear the visited flag to ensure that the critical counts are collected properly. - cur->set_visited_for_critical_count(false); - } + for (; JavaThread *cur = jtiwh.next(); ) { + assert(cur->safepoint_state()->is_running(), "Illegal initial state"); + // Clear the visited flag to ensure that the critical counts are collected properly. + cur->set_visited_for_critical_count(false); + } #endif // ASSERT - if (SafepointTimeout) - safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS; + if (SafepointTimeout) + safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS; - // Iterate through all threads until it have been determined how to stop them all at a safepoint - unsigned int iterations = 0; - int steps = 0 ; - while(still_running > 0) { - for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) { - assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended"); - ThreadSafepointState *cur_state = cur->safepoint_state(); - if (cur_state->is_running()) { - cur_state->examine_state_of_thread(); - if (!cur_state->is_running()) { - still_running--; - // consider adjusting steps downward: - // steps = 0 - // steps -= NNN - // steps >>= 1 - // steps = MIN(steps, 2000-100) - // if (iterations != 0) steps -= NNN - } - LogTarget(Trace, safepoint) lt; - if (lt.is_enabled()) { - ResourceMark rm; - LogStream ls(lt); - cur_state->print_on(&ls); + // Iterate through all threads until it have been determined how to stop them all at a safepoint + int steps = 0 ; + while(still_running > 0) { + jtiwh.rewind(); + for (; JavaThread *cur = jtiwh.next(); ) { + assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended"); + ThreadSafepointState *cur_state = cur->safepoint_state(); + if (cur_state->is_running()) { + cur_state->examine_state_of_thread(); + if (!cur_state->is_running()) { + still_running--; + // consider adjusting steps downward: + // steps = 0 + // steps -= NNN + // steps >>= 1 + // steps = MIN(steps, 2000-100) + // if (iterations != 0) steps -= NNN + } + LogTarget(Trace, safepoint) lt; + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + cur_state->print_on(&ls); + } } } - } - if (iterations == 0) { - initial_running = still_running; - if (PrintSafepointStatistics) { - begin_statistics(nof_threads, still_running); - } - } - - if (still_running > 0) { - // Check for if it takes to long - if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) { - print_safepoint_timeout(_spinning_timeout); + if (iterations == 0) { + initial_running = still_running; + if (PrintSafepointStatistics) { + begin_statistics(nof_threads, still_running); + } } - // Spin to avoid context switching. - // There's a tension between allowing the mutators to run (and rendezvous) - // vs spinning. As the VM thread spins, wasting cycles, it consumes CPU that - // a mutator might otherwise use profitably to reach a safepoint. Excessive - // spinning by the VM thread on a saturated system can increase rendezvous latency. - // Blocking or yielding incur their own penalties in the form of context switching - // and the resultant loss of $ residency. - // - // Further complicating matters is that yield() does not work as naively expected - // on many platforms -- yield() does not guarantee that any other ready threads - // will run. As such we revert to naked_short_sleep() after some number of iterations. - // nakes_short_sleep() is implemented as a short unconditional sleep. - // Typical operating systems round a "short" sleep period up to 10 msecs, so sleeping - // can actually increase the time it takes the VM thread to detect that a system-wide - // stop-the-world safepoint has been reached. In a pathological scenario such as that - // described in CR6415670 the VMthread may sleep just before the mutator(s) become safe. - // In that case the mutators will be stalled waiting for the safepoint to complete and the - // the VMthread will be sleeping, waiting for the mutators to rendezvous. The VMthread - // will eventually wake up and detect that all mutators are safe, at which point - // we'll again make progress. - // - // Beware too that that the VMThread typically runs at elevated priority. - // Its default priority is higher than the default mutator priority. - // Obviously, this complicates spinning. - // - // Note too that on Windows XP SwitchThreadTo() has quite different behavior than Sleep(0). - // Sleep(0) will _not yield to lower priority threads, while SwitchThreadTo() will. - // - // See the comments in synchronizer.cpp for additional remarks on spinning. - // - // In the future we might: - // 1. Modify the safepoint scheme to avoid potentially unbounded spinning. - // This is tricky as the path used by a thread exiting the JVM (say on - // on JNI call-out) simply stores into its state field. The burden - // is placed on the VM thread, which must poll (spin). - // 2. Find something useful to do while spinning. If the safepoint is GC-related - // we might aggressively scan the stacks of threads that are already safe. - // 3. Use Solaris schedctl to examine the state of the still-running mutators. - // If all the mutators are ONPROC there's no reason to sleep or yield. - // 4. YieldTo() any still-running mutators that are ready but OFFPROC. - // 5. Check system saturation. If the system is not fully saturated then - // simply spin and avoid sleep/yield. - // 6. As still-running mutators rendezvous they could unpark the sleeping - // VMthread. This works well for still-running mutators that become - // safe. The VMthread must still poll for mutators that call-out. - // 7. Drive the policy on time-since-begin instead of iterations. - // 8. Consider making the spin duration a function of the # of CPUs: - // Spin = (((ncpus-1) * M) + K) + F(still_running) - // Alternately, instead of counting iterations of the outer loop - // we could count the # of threads visited in the inner loop, above. - // 9. On windows consider using the return value from SwitchThreadTo() - // to drive subsequent spin/SwitchThreadTo()/Sleep(N) decisions. - - if (SafepointMechanism::uses_global_page_poll() && int(iterations) == DeferPollingPageLoopCount) { - guarantee (PageArmed == 0, "invariant") ; - PageArmed = 1 ; - os::make_polling_page_unreadable(); - } - - // Instead of (ncpus > 1) consider either (still_running < (ncpus + EPSILON)) or - // ((still_running + _waiting_to_block - TryingToBlock)) < ncpus) - ++steps ; - if (ncpus > 1 && steps < SafepointSpinBeforeYield) { - SpinPause() ; // MP-Polite spin - } else - if (steps < DeferThrSuspendLoopCount) { - os::naked_yield() ; - } else { - os::naked_short_sleep(1); + if (still_running > 0) { + // Check for if it takes to long + if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) { + print_safepoint_timeout(_spinning_timeout); } - iterations ++ ; + // Spin to avoid context switching. + // There's a tension between allowing the mutators to run (and rendezvous) + // vs spinning. As the VM thread spins, wasting cycles, it consumes CPU that + // a mutator might otherwise use profitably to reach a safepoint. Excessive + // spinning by the VM thread on a saturated system can increase rendezvous latency. + // Blocking or yielding incur their own penalties in the form of context switching + // and the resultant loss of $ residency. + // + // Further complicating matters is that yield() does not work as naively expected + // on many platforms -- yield() does not guarantee that any other ready threads + // will run. As such we revert to naked_short_sleep() after some number of iterations. + // nakes_short_sleep() is implemented as a short unconditional sleep. + // Typical operating systems round a "short" sleep period up to 10 msecs, so sleeping + // can actually increase the time it takes the VM thread to detect that a system-wide + // stop-the-world safepoint has been reached. In a pathological scenario such as that + // described in CR6415670 the VMthread may sleep just before the mutator(s) become safe. + // In that case the mutators will be stalled waiting for the safepoint to complete and the + // the VMthread will be sleeping, waiting for the mutators to rendezvous. The VMthread + // will eventually wake up and detect that all mutators are safe, at which point + // we'll again make progress. + // + // Beware too that that the VMThread typically runs at elevated priority. + // Its default priority is higher than the default mutator priority. + // Obviously, this complicates spinning. + // + // Note too that on Windows XP SwitchThreadTo() has quite different behavior than Sleep(0). + // Sleep(0) will _not yield to lower priority threads, while SwitchThreadTo() will. + // + // See the comments in synchronizer.cpp for additional remarks on spinning. + // + // In the future we might: + // 1. Modify the safepoint scheme to avoid potentially unbounded spinning. + // This is tricky as the path used by a thread exiting the JVM (say on + // on JNI call-out) simply stores into its state field. The burden + // is placed on the VM thread, which must poll (spin). + // 2. Find something useful to do while spinning. If the safepoint is GC-related + // we might aggressively scan the stacks of threads that are already safe. + // 3. Use Solaris schedctl to examine the state of the still-running mutators. + // If all the mutators are ONPROC there's no reason to sleep or yield. + // 4. YieldTo() any still-running mutators that are ready but OFFPROC. + // 5. Check system saturation. If the system is not fully saturated then + // simply spin and avoid sleep/yield. + // 6. As still-running mutators rendezvous they could unpark the sleeping + // VMthread. This works well for still-running mutators that become + // safe. The VMthread must still poll for mutators that call-out. + // 7. Drive the policy on time-since-begin instead of iterations. + // 8. Consider making the spin duration a function of the # of CPUs: + // Spin = (((ncpus-1) * M) + K) + F(still_running) + // Alternately, instead of counting iterations of the outer loop + // we could count the # of threads visited in the inner loop, above. + // 9. On windows consider using the return value from SwitchThreadTo() + // to drive subsequent spin/SwitchThreadTo()/Sleep(N) decisions. + + if (SafepointMechanism::uses_global_page_poll() && int(iterations) == DeferPollingPageLoopCount) { + guarantee (PageArmed == 0, "invariant") ; + PageArmed = 1 ; + os::make_polling_page_unreadable(); + } + + // Instead of (ncpus > 1) consider either (still_running < (ncpus + EPSILON)) or + // ((still_running + _waiting_to_block - TryingToBlock)) < ncpus) + ++steps ; + if (ncpus > 1 && steps < SafepointSpinBeforeYield) { + SpinPause() ; // MP-Polite spin + } else + if (steps < DeferThrSuspendLoopCount) { + os::naked_yield() ; + } else { + os::naked_short_sleep(1); + } + + iterations ++ ; + } + assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long"); } - assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long"); - } + } // ThreadsListHandle destroyed here. assert(still_running == 0, "sanity check"); if (PrintSafepointStatistics) { @@ -341,7 +346,7 @@ void SafepointSynchronize::begin() { sync_event.set_iterations(iterations); sync_event.commit(); } - } //EventSafepointStateSync + } // EventSafepointStateSynchronization destroyed here. // wait until all threads are stopped { @@ -393,8 +398,8 @@ void SafepointSynchronize::begin() { } // EventSafepointWaitBlocked #ifdef ASSERT - for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) { - // make sure all the threads were visited + // Make sure all the threads were visited. + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) { assert(cur->was_visited_for_critical_count(), "missed a thread"); } #endif // ASSERT @@ -452,81 +457,86 @@ void SafepointSynchronize::end() { end_statistics(os::javaTimeNanos()); } + { + JavaThreadIteratorWithHandle jtiwh; #ifdef ASSERT - // A pending_exception cannot be installed during a safepoint. The threads - // may install an async exception after they come back from a safepoint into - // pending_exception after they unblock. But that should happen later. - for (JavaThread *cur = Threads::first(); cur; cur = cur->next()) { - assert (!(cur->has_pending_exception() && - cur->safepoint_state()->is_at_poll_safepoint()), - "safepoint installed a pending exception"); - } + // A pending_exception cannot be installed during a safepoint. The threads + // may install an async exception after they come back from a safepoint into + // pending_exception after they unblock. But that should happen later. + for (; JavaThread *cur = jtiwh.next(); ) { + assert (!(cur->has_pending_exception() && + cur->safepoint_state()->is_at_poll_safepoint()), + "safepoint installed a pending exception"); + } #endif // ASSERT - if (PageArmed) { - assert(SafepointMechanism::uses_global_page_poll(), "sanity"); - // Make polling safepoint aware - os::make_polling_page_readable(); - PageArmed = 0 ; - } - - if (SafepointMechanism::uses_global_page_poll()) { - // Remove safepoint check from interpreter - Interpreter::ignore_safepoints(); - } - - { - MutexLocker mu(Safepoint_lock); - - assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization"); - - if (SafepointMechanism::uses_thread_local_poll()) { - _state = _not_synchronized; - OrderAccess::storestore(); // global state -> local state - for (JavaThread *current = Threads::first(); current; current = current->next()) { - ThreadSafepointState* cur_state = current->safepoint_state(); - cur_state->restart(); // TSS _running - SafepointMechanism::disarm_local_poll(current); // release store, local state -> polling page - } - log_debug(safepoint)("Leaving safepoint region"); - } else { - // Set to not synchronized, so the threads will not go into the signal_thread_blocked method - // when they get restarted. - _state = _not_synchronized; - OrderAccess::fence(); - - log_debug(safepoint)("Leaving safepoint region"); - - // Start suspended threads - for (JavaThread *current = Threads::first(); current; current = current->next()) { - // A problem occurring on Solaris is when attempting to restart threads - // the first #cpus - 1 go well, but then the VMThread is preempted when we get - // to the next one (since it has been running the longest). We then have - // to wait for a cpu to become available before we can continue restarting - // threads. - // FIXME: This causes the performance of the VM to degrade when active and with - // large numbers of threads. Apparently this is due to the synchronous nature - // of suspending threads. - // - // TODO-FIXME: the comments above are vestigial and no longer apply. - // Furthermore, using solaris' schedctl in this particular context confers no benefit - if (VMThreadHintNoPreempt) { - os::hint_no_preempt(); - } - ThreadSafepointState* cur_state = current->safepoint_state(); - assert(cur_state->type() != ThreadSafepointState::_running, "Thread not suspended at safepoint"); - cur_state->restart(); - assert(cur_state->is_running(), "safepoint state has not been reset"); - } + if (PageArmed) { + assert(SafepointMechanism::uses_global_page_poll(), "sanity"); + // Make polling safepoint aware + os::make_polling_page_readable(); + PageArmed = 0 ; } - RuntimeService::record_safepoint_end(); + if (SafepointMechanism::uses_global_page_poll()) { + // Remove safepoint check from interpreter + Interpreter::ignore_safepoints(); + } - // Release threads lock, so threads can be created/destroyed again. It will also starts all threads - // blocked in signal_thread_blocked - Threads_lock->unlock(); + { + MutexLocker mu(Safepoint_lock); + + assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization"); + + if (SafepointMechanism::uses_thread_local_poll()) { + _state = _not_synchronized; + OrderAccess::storestore(); // global state -> local state + jtiwh.rewind(); + for (; JavaThread *current = jtiwh.next(); ) { + ThreadSafepointState* cur_state = current->safepoint_state(); + cur_state->restart(); // TSS _running + SafepointMechanism::disarm_local_poll(current); // release store, local state -> polling page + } + log_debug(safepoint)("Leaving safepoint region"); + } else { + // Set to not synchronized, so the threads will not go into the signal_thread_blocked method + // when they get restarted. + _state = _not_synchronized; + OrderAccess::fence(); + + log_debug(safepoint)("Leaving safepoint region"); + + // Start suspended threads + jtiwh.rewind(); + for (; JavaThread *current = jtiwh.next(); ) { + // A problem occurring on Solaris is when attempting to restart threads + // the first #cpus - 1 go well, but then the VMThread is preempted when we get + // to the next one (since it has been running the longest). We then have + // to wait for a cpu to become available before we can continue restarting + // threads. + // FIXME: This causes the performance of the VM to degrade when active and with + // large numbers of threads. Apparently this is due to the synchronous nature + // of suspending threads. + // + // TODO-FIXME: the comments above are vestigial and no longer apply. + // Furthermore, using solaris' schedctl in this particular context confers no benefit + if (VMThreadHintNoPreempt) { + os::hint_no_preempt(); + } + ThreadSafepointState* cur_state = current->safepoint_state(); + assert(cur_state->type() != ThreadSafepointState::_running, "Thread not suspended at safepoint"); + cur_state->restart(); + assert(cur_state->is_running(), "safepoint state has not been reset"); + } + } + + RuntimeService::record_safepoint_end(); + + // Release threads lock, so threads can be created/destroyed again. + // It will also release all threads blocked in signal_thread_blocked. + Threads_lock->unlock(); + } + } // ThreadsListHandle destroyed here. - } Universe::heap()->safepoint_synchronize_end(); // record this time so VMThread can keep track how much time has elapsed // since last safepoint. @@ -915,12 +925,11 @@ void SafepointSynchronize::print_safepoint_timeout(SafepointTimeoutReason reason tty->print_cr("# SafepointSynchronize::begin: Threads which did not reach the safepoint:"); ThreadSafepointState *cur_state; ResourceMark rm; - for (JavaThread *cur_thread = Threads::first(); cur_thread; - cur_thread = cur_thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur_thread = jtiwh.next(); ) { cur_state = cur_thread->safepoint_state(); if (cur_thread->thread_state() != _thread_blocked && - ((reason == _spinning_timeout && cur_state->is_running()) || + ((reason == _spinning_timeout && cur_state->is_running()) || (reason == _blocking_timeout && !cur_state->has_called_back()))) { tty->print("# "); cur_thread->print(); @@ -1427,7 +1436,7 @@ void SafepointSynchronize::print_state() { tty->print_cr("State: %s", (_state == _synchronizing) ? "synchronizing" : "synchronized"); - for (JavaThread *cur = Threads::first(); cur; cur = cur->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) { cur->safepoint_state()->print(); } } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 8e4c90f9199..abb070dffd7 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -970,7 +970,7 @@ JNI_ENTRY(void*, throw_unsatisfied_link_error(JNIEnv* env, ...)) { // We return a bad value here to make sure that the exception is // forwarded before we look at the return value. - THROW_(vmSymbols::java_lang_UnsatisfiedLinkError(), (void*)badJNIHandle); + THROW_(vmSymbols::java_lang_UnsatisfiedLinkError(), (void*)badAddress); } JNI_END diff --git a/src/hotspot/share/runtime/statSampler.cpp b/src/hotspot/share/runtime/statSampler.cpp index 6cdd0743ad1..3f995380468 100644 --- a/src/hotspot/share/runtime/statSampler.cpp +++ b/src/hotspot/share/runtime/statSampler.cpp @@ -32,6 +32,7 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/os.hpp" +#include "runtime/perfData.inline.hpp" #include "runtime/statSampler.hpp" #include "runtime/vm_version.hpp" diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index d54b0d8b30a..6b8898959c8 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -894,7 +894,7 @@ ObjectSynchronizer::LockOwnership ObjectSynchronizer::query_lock_ownership } // FIXME: jvmti should call this -JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) { +JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_obj) { if (UseBiasedLocking) { if (SafepointSynchronize::is_at_safepoint()) { BiasedLocking::revoke_at_safepoint(h_obj); @@ -923,7 +923,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) { if (owner != NULL) { // owning_thread_from_monitor_owner() may also return NULL here - return Threads::owning_thread_from_monitor_owner(owner, doLock); + return Threads::owning_thread_from_monitor_owner(t_list, owner); } // Unlocked case, header in place diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp index ba3ac60a267..415c222ab6f 100644 --- a/src/hotspot/share/runtime/synchronizer.hpp +++ b/src/hotspot/share/runtime/synchronizer.hpp @@ -32,6 +32,7 @@ #include "runtime/perfData.hpp" class ObjectMonitor; +class ThreadsList; struct DeflateMonitorCounters { int nInuse; // currently associated with objects @@ -125,7 +126,7 @@ class ObjectSynchronizer : AllStatic { static bool current_thread_holds_lock(JavaThread* thread, Handle h_obj); static LockOwnership query_lock_ownership(JavaThread * self, Handle h_obj); - static JavaThread* get_lock_owner(Handle h_obj, bool doLock); + static JavaThread* get_lock_owner(ThreadsList * t_list, Handle h_obj); // JNI detach support static void release_monitors_owned_by_thread(TRAPS); diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 48c757fbd83..d4191b0d89f 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -71,12 +71,12 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniPeriodicChecker.hpp" -#include "runtime/timerTrace.hpp" #include "runtime/memprofiler.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" +#include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" #include "runtime/safepointMechanism.inline.hpp" #include "runtime/sharedRuntime.hpp" @@ -86,6 +86,9 @@ #include "runtime/task.hpp" #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/threadSMR.inline.hpp" +#include "runtime/timer.hpp" +#include "runtime/timerTrace.hpp" #include "runtime/vframe.hpp" #include "runtime/vframeArray.hpp" #include "runtime/vframe_hp.hpp" @@ -104,6 +107,7 @@ #include "utilities/events.hpp" #include "utilities/macros.hpp" #include "utilities/preserveException.hpp" +#include "utilities/resourceHash.hpp" #include "utilities/vmError.hpp" #if INCLUDE_ALL_GCS #include "gc/cms/concurrentMarkSweepThread.hpp" @@ -195,13 +199,19 @@ void* Thread::allocate(size_t size, bool throw_excpt, MEMFLAGS flags) { void Thread::operator delete(void* p) { if (UseBiasedLocking) { - void* real_malloc_addr = ((Thread*) p)->_real_malloc_address; - FreeHeap(real_malloc_addr); + FreeHeap(((Thread*) p)->_real_malloc_address); } else { FreeHeap(p); } } +void JavaThread::smr_delete() { + if (_on_thread_list) { + Threads::smr_delete(this); + } else { + delete this; + } +} // Base class for all threads: VMThread, WatcherThread, ConcurrentMarkSweepThread, // JavaThread @@ -227,6 +237,9 @@ Thread::Thread() { // This initial value ==> never claimed. _oops_do_parity = 0; + _threads_hazard_ptr = NULL; + _nested_threads_hazard_ptr = NULL; + _nested_threads_hazard_ptr_cnt = 0; // the handle mark links itself to last_handle_mark new HandleMark(this); @@ -398,9 +411,15 @@ void Thread::run() { } #ifdef ASSERT -// Private method to check for dangling thread pointer -void check_for_dangling_thread_pointer(Thread *thread) { - assert(!thread->is_Java_thread() || Thread::current() == thread || Threads_lock->owned_by_self(), +// A JavaThread is considered "dangling" if it is not the current +// thread, has been added the Threads list, the system is not at a +// safepoint and the Thread is not "protected". +// +void Thread::check_for_dangling_thread_pointer(Thread *thread) { + assert(!thread->is_Java_thread() || Thread::current() == thread || + !((JavaThread *) thread)->on_thread_list() || + SafepointSynchronize::is_at_safepoint() || + Threads::is_a_protected_JavaThread_with_lock((JavaThread *) thread), "possibility of dangling Thread pointer"); } #endif @@ -732,6 +751,37 @@ bool JavaThread::wait_for_ext_suspend_completion(int retries, int delay, return false; } +// Called from API entry points which perform stack walking. If the +// associated JavaThread is the current thread, then wait_for_suspend +// is not used. Otherwise, it determines if we should wait for the +// "other" thread to complete external suspension. (NOTE: in future +// releases the suspension mechanism should be reimplemented so this +// is not necessary.) +// +bool +JavaThread::is_thread_fully_suspended(bool wait_for_suspend, uint32_t *bits) { + if (this != JavaThread::current()) { + // "other" threads require special handling. + if (wait_for_suspend) { + // We are allowed to wait for the external suspend to complete + // so give the other thread a chance to get suspended. + if (!wait_for_ext_suspend_completion(SuspendRetryCount, + SuspendRetryDelay, bits)) { + // Didn't make it so let the caller know. + return false; + } + } + // We aren't allowed to wait for the external suspend to complete + // so if the other thread isn't externally suspended we need to + // let the caller know. + else if (!is_ext_suspend_completed_with_lock(bits)) { + return false; + } + } + + return true; +} + #ifndef PRODUCT void JavaThread::record_jump(address target, address instr, const char* file, int line) { @@ -810,9 +860,33 @@ void Thread::print_on(outputStream* st) const { ext().print_on(st); osthread()->print_on(st); } + if (_threads_hazard_ptr != NULL) { + st->print("_threads_hazard_ptr=" INTPTR_FORMAT, p2i(_threads_hazard_ptr)); + } + if (_nested_threads_hazard_ptr != NULL) { + print_nested_threads_hazard_ptrs_on(st); + } + st->print(" "); debug_only(if (WizardMode) print_owned_locks_on(st);) } +void Thread::print_nested_threads_hazard_ptrs_on(outputStream* st) const { + assert(_nested_threads_hazard_ptr != NULL, "must be set to print"); + + if (EnableThreadSMRStatistics) { + st->print(", _nested_threads_hazard_ptr_cnt=%u", _nested_threads_hazard_ptr_cnt); + } + st->print(", _nested_threads_hazard_ptrs="); + for (NestedThreadsList* node = _nested_threads_hazard_ptr; node != NULL; + node = node->next()) { + if (node != _nested_threads_hazard_ptr) { + // First node does not need a comma-space separator. + st->print(", "); + } + st->print(INTPTR_FORMAT, p2i(node->t_list())); + } +} + // Thread::print_on_error() is called by fatal error handler. Don't use // any lock or allocate memory. void Thread::print_on_error(outputStream* st, char* buf, int buflen) const { @@ -834,6 +908,13 @@ void Thread::print_on_error(outputStream* st, char* buf, int buflen) const { if (osthread()) { st->print(" [id=%d]", osthread()->thread_id()); } + + if (_threads_hazard_ptr != NULL) { + st->print(" _threads_hazard_ptr=" INTPTR_FORMAT, p2i(_threads_hazard_ptr)); + } + if (_nested_threads_hazard_ptr != NULL) { + print_nested_threads_hazard_ptrs_on(st); + } } void Thread::print_value_on(outputStream* st) const { @@ -871,8 +952,8 @@ bool Thread::owns_locks_but_compiled_lock() const { #ifndef PRODUCT -// The flag: potential_vm_operation notifies if this particular safepoint state could potential -// invoke the vm-thread (i.e., and oop allocation). In that case, we also have to make sure that +// The flag: potential_vm_operation notifies if this particular safepoint state could potentially +// invoke the vm-thread (e.g., an oop allocation). In that case, we also have to make sure that // no threads which allow_vm_block's are held void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) { // Check if current thread is allowed to block at a safepoint @@ -1399,10 +1480,11 @@ bool jvmci_counters_include(JavaThread* thread) { void JavaThread::collect_counters(typeArrayOop array) { if (JVMCICounterSize > 0) { MutexLocker tl(Threads_lock); + JavaThreadIteratorWithHandle jtiwh; for (int i = 0; i < array->length(); i++) { array->long_at_put(i, _jvmci_old_thread_counters[i]); } - for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) { + for (; JavaThread *tp = jtiwh.next(); ) { if (jvmci_counters_include(tp)) { for (int i = 0; i < array->length(); i++) { array->long_at_put(i, array->long_at(i) + tp->_jvmci_counters[i]); @@ -1435,6 +1517,7 @@ void JavaThread::initialize() { clear_must_deopt_id(); set_monitor_chunks(NULL); set_next(NULL); + _on_thread_list = false; set_thread_state(_thread_new); _terminated = _not_terminated; _privileged_stack_top = NULL; @@ -1715,12 +1798,12 @@ void JavaThread::thread_main_inner() { DTRACE_THREAD_PROBE(stop, this); this->exit(false); - delete this; + this->smr_delete(); } static void ensure_join(JavaThread* thread) { - // We do not need to grap the Threads_lock, since we are operating on ourself. + // We do not need to grab the Threads_lock, since we are operating on ourself. Handle threadObj(thread, thread->threadObj()); assert(threadObj.not_null(), "java thread object must exist"); ObjectLocker lock(threadObj, thread); @@ -1742,6 +1825,15 @@ static void ensure_join(JavaThread* thread) { void JavaThread::exit(bool destroy_vm, ExitType exit_type) { assert(this == JavaThread::current(), "thread consistency check"); + elapsedTimer _timer_exit_phase1; + elapsedTimer _timer_exit_phase2; + elapsedTimer _timer_exit_phase3; + elapsedTimer _timer_exit_phase4; + + if (log_is_enabled(Debug, os, thread, timer)) { + _timer_exit_phase1.start(); + } + HandleMark hm(this); Handle uncaught_exception(this, this->pending_exception()); this->clear_pending_exception(); @@ -1841,12 +1933,20 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { // before_exit() has already posted JVMTI THREAD_END events } + if (log_is_enabled(Debug, os, thread, timer)) { + _timer_exit_phase1.stop(); + _timer_exit_phase2.start(); + } // Notify waiters on thread object. This has to be done after exit() is called // on the thread (if the thread is the last thread in a daemon ThreadGroup the // group should have the destroyed bit set before waiters are notified). ensure_join(this); assert(!this->has_pending_exception(), "ensure_join should have cleared"); + if (log_is_enabled(Debug, os, thread, timer)) { + _timer_exit_phase2.stop(); + _timer_exit_phase3.start(); + } // 6282335 JNI DetachCurrentThread spec states that all Java monitors // held by this thread must be released. The spec does not distinguish // between JNI-acquired and regular Java monitors. We can only see @@ -1914,12 +2014,26 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { exit_type == JavaThread::normal_exit ? "exiting" : "detaching", os::current_thread_id()); + if (log_is_enabled(Debug, os, thread, timer)) { + _timer_exit_phase3.stop(); + _timer_exit_phase4.start(); + } // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); - // If someone set a handshake on us just as we entered exit path, we simple cancel it. - if (ThreadLocalHandshakes) { - cancel_handshake(); + if (log_is_enabled(Debug, os, thread, timer)) { + _timer_exit_phase4.stop(); + ResourceMark rm(this); + log_debug(os, thread, timer)("name='%s'" + ", exit-phase1=" JLONG_FORMAT + ", exit-phase2=" JLONG_FORMAT + ", exit-phase3=" JLONG_FORMAT + ", exit-phase4=" JLONG_FORMAT, + get_thread_name(), + _timer_exit_phase1.milliseconds(), + _timer_exit_phase2.milliseconds(), + _timer_exit_phase3.milliseconds(), + _timer_exit_phase4.milliseconds()); } } @@ -1980,7 +2094,7 @@ void JavaThread::cleanup_failed_attach_current_thread() { #endif // INCLUDE_ALL_GCS Threads::remove(this); - delete this; + this->smr_delete(); } @@ -2235,10 +2349,9 @@ void JavaThread::send_thread_stop(oop java_throwable) { // + Target thread will not enter any new monitors // void JavaThread::java_suspend() { - { MutexLocker mu(Threads_lock); - if (!Threads::includes(this) || is_exiting() || this->threadObj() == NULL) { - return; - } + ThreadsListHandle tlh; + if (!tlh.includes(this) || threadObj() == NULL || is_exiting()) { + return; } { MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag); @@ -2327,14 +2440,8 @@ int JavaThread::java_suspend_self() { // verify the JavaThread has not yet been published in the Threads::list, and // hence doesn't need protection from concurrent access at this stage void JavaThread::verify_not_published() { - if (!Threads_lock->owned_by_self()) { - MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); - assert(!Threads::includes(this), - "java thread shouldn't have been published yet!"); - } else { - assert(!Threads::includes(this), - "java thread shouldn't have been published yet!"); - } + ThreadsListHandle tlh; + assert(!tlh.includes(this), "JavaThread shouldn't have been published yet!"); } #endif @@ -2451,7 +2558,8 @@ void JavaThread::java_resume() { // Sanity check: thread is gone, has started exiting or the thread // was not externally suspended. - if (!Threads::includes(this) || is_exiting() || !is_external_suspend()) { + ThreadsListHandle tlh; + if (!tlh.includes(this) || is_exiting() || !is_external_suspend()) { return; } @@ -2925,6 +3033,13 @@ void JavaThread::print_on_error(outputStream* st, char *buf, int buflen) const { st->print(", stack(" PTR_FORMAT "," PTR_FORMAT ")", p2i(stack_end()), p2i(stack_base())); st->print("]"); + + if (_threads_hazard_ptr != NULL) { + st->print(" _threads_hazard_ptr=" INTPTR_FORMAT, p2i(_threads_hazard_ptr)); + } + if (_nested_threads_hazard_ptr != NULL) { + print_nested_threads_hazard_ptrs_on(st); + } return; } @@ -3318,23 +3433,140 @@ void CodeCacheSweeperThread::nmethods_do(CodeBlobClosure* cf) { // ======= Threads ======== // The Threads class links together all active threads, and provides -// operations over all threads. It is protected by its own Mutex -// lock, which is also used in other contexts to protect thread -// operations from having the thread being operated on from exiting -// and going away unexpectedly (e.g., safepoint synchronization) +// operations over all threads. It is protected by the Threads_lock, +// which is also used in other global contexts like safepointing. +// ThreadsListHandles are used to safely perform operations on one +// or more threads without the risk of the thread exiting during the +// operation. +// +// Note: The Threads_lock is currently more widely used than we +// would like. We are actively migrating Threads_lock uses to other +// mechanisms in order to reduce Threads_lock contention. + +JavaThread* Threads::_thread_list = NULL; +int Threads::_number_of_threads = 0; +int Threads::_number_of_non_daemon_threads = 0; +int Threads::_return_code = 0; +int Threads::_thread_claim_parity = 0; +size_t JavaThread::_stack_size_at_create = 0; +// Safe Memory Reclamation (SMR) support: +Monitor* Threads::_smr_delete_lock = + new Monitor(Monitor::special, "smr_delete_lock", + false /* allow_vm_block */, + Monitor::_safepoint_check_never); +// The '_cnt', '_max' and '_times" fields are enabled via +// -XX:+EnableThreadSMRStatistics: + +// # of parallel threads in _smr_delete_lock->wait(). +// Impl note: Hard to imagine > 64K waiting threads so this could be 16-bit, +// but there is no nice 16-bit _FORMAT support. +uint Threads::_smr_delete_lock_wait_cnt = 0; + +// Max # of parallel threads in _smr_delete_lock->wait(). +// Impl note: See _smr_delete_lock_wait_cnt note. +uint Threads::_smr_delete_lock_wait_max = 0; + +// Flag to indicate when an _smr_delete_lock->notify() is needed. +// Impl note: See _smr_delete_lock_wait_cnt note. +volatile uint Threads::_smr_delete_notify = 0; + +// # of threads deleted over VM lifetime. +// Impl note: Atomically incremented over VM lifetime so use unsigned for more +// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc +// isn't available everywhere (or is it?). +volatile uint Threads::_smr_deleted_thread_cnt = 0; + +// Max time in millis to delete a thread. +// Impl note: 16-bit might be too small on an overloaded machine. Use +// unsigned since this is a time value. Set via Atomic::cmpxchg() in a +// loop for correctness. +volatile uint Threads::_smr_deleted_thread_time_max = 0; + +// Cumulative time in millis to delete threads. +// Impl note: Atomically added to over VM lifetime so use unsigned for more +// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc +// isn't available everywhere (or is it?). +volatile uint Threads::_smr_deleted_thread_times = 0; + +ThreadsList* volatile Threads::_smr_java_thread_list = new ThreadsList(0); + +// # of ThreadsLists allocated over VM lifetime. +// Impl note: We allocate a new ThreadsList for every thread create and +// every thread delete so we need a bigger type than the +// _smr_deleted_thread_cnt field. +uint64_t Threads::_smr_java_thread_list_alloc_cnt = 1; + +// # of ThreadsLists freed over VM lifetime. +// Impl note: See _smr_java_thread_list_alloc_cnt note. +uint64_t Threads::_smr_java_thread_list_free_cnt = 0; + +// Max size ThreadsList allocated. +// Impl note: Max # of threads alive at one time should fit in unsigned 32-bit. +uint Threads::_smr_java_thread_list_max = 0; + +// Max # of nested ThreadsLists for a thread. +// Impl note: Hard to imagine > 64K nested ThreadsLists so this could be +// 16-bit, but there is no nice 16-bit _FORMAT support. +uint Threads::_smr_nested_thread_list_max = 0; + +// # of ThreadsListHandles deleted over VM lifetime. +// Impl note: Atomically incremented over VM lifetime so use unsigned for +// more range. There will be fewer ThreadsListHandles than threads so +// unsigned 32-bit should be fine. +volatile uint Threads::_smr_tlh_cnt = 0; + +// Max time in millis to delete a ThreadsListHandle. +// Impl note: 16-bit might be too small on an overloaded machine. Use +// unsigned since this is a time value. Set via Atomic::cmpxchg() in a +// loop for correctness. +volatile uint Threads::_smr_tlh_time_max = 0; + +// Cumulative time in millis to delete ThreadsListHandles. +// Impl note: Atomically added to over VM lifetime so use unsigned for more +// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc +// isn't available everywhere (or is it?). +volatile uint Threads::_smr_tlh_times = 0; + +ThreadsList* Threads::_smr_to_delete_list = NULL; + +// # of parallel ThreadsLists on the to-delete list. +// Impl note: Hard to imagine > 64K ThreadsLists needing to be deleted so +// this could be 16-bit, but there is no nice 16-bit _FORMAT support. +uint Threads::_smr_to_delete_list_cnt = 0; + +// Max # of parallel ThreadsLists on the to-delete list. +// Impl note: See _smr_to_delete_list_cnt note. +uint Threads::_smr_to_delete_list_max = 0; -JavaThread* Threads::_thread_list = NULL; -int Threads::_number_of_threads = 0; -int Threads::_number_of_non_daemon_threads = 0; -int Threads::_return_code = 0; -int Threads::_thread_claim_parity = 0; -size_t JavaThread::_stack_size_at_create = 0; #ifdef ASSERT -bool Threads::_vm_complete = false; +bool Threads::_vm_complete = false; #endif +static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) { + Prefetch::read((void*)addr, prefetch_interval); + return *addr; +} + +// Possibly the ugliest for loop the world has seen. C++ does not allow +// multiple types in the declaration section of the for loop. In this case +// we are only dealing with pointers and hence can cast them. It looks ugly +// but macros are ugly and therefore it's fine to make things absurdly ugly. +#define DO_JAVA_THREADS(LIST, X) \ + for (JavaThread *MACRO_scan_interval = (JavaThread*)(uintptr_t)PrefetchScanIntervalInBytes, \ + *MACRO_list = (JavaThread*)(LIST), \ + **MACRO_end = ((JavaThread**)((ThreadsList*)MACRO_list)->threads()) + ((ThreadsList*)MACRO_list)->length(), \ + **MACRO_current_p = (JavaThread**)((ThreadsList*)MACRO_list)->threads(), \ + *X = (JavaThread*)prefetch_and_load_ptr((void**)MACRO_current_p, (intx)MACRO_scan_interval); \ + MACRO_current_p != MACRO_end; \ + MACRO_current_p++, \ + X = (JavaThread*)prefetch_and_load_ptr((void**)MACRO_current_p, (intx)MACRO_scan_interval)) + +inline ThreadsList* Threads::get_smr_java_thread_list() { + return (ThreadsList*)OrderAccess::load_acquire(&_smr_java_thread_list); +} + // All JavaThreads -#define ALL_JAVA_THREADS(X) for (JavaThread* X = _thread_list; X; X = X->next()) +#define ALL_JAVA_THREADS(X) DO_JAVA_THREADS(get_smr_java_thread_list(), X) // All JavaThreads + all non-JavaThreads (i.e., every thread in the system) void Threads::threads_do(ThreadClosure* tc) { @@ -3435,6 +3667,240 @@ static void call_initPhase3(TRAPS) { vmSymbols::void_method_signature(), CHECK); } +// Safe Memory Reclamation (SMR) support: +// + +// Acquire a stable ThreadsList. +// +ThreadsList *Threads::acquire_stable_list(Thread *self, bool is_ThreadsListSetter) { + assert(self != NULL, "sanity check"); + // acquire_stable_list_nested_path() will grab the Threads_lock + // so let's make sure the ThreadsListHandle is in a safe place. + // ThreadsListSetter cannot make this check on this code path. + debug_only(if (!is_ThreadsListSetter && StrictSafepointChecks) self->check_for_valid_safepoint_state(/* potential_vm_operation */ false);) + + if (self->get_threads_hazard_ptr() == NULL) { + // The typical case is first. + return acquire_stable_list_fast_path(self); + } + + // The nested case is rare. + return acquire_stable_list_nested_path(self); +} + +// Fast path (and lock free) way to acquire a stable ThreadsList. +// +ThreadsList *Threads::acquire_stable_list_fast_path(Thread *self) { + assert(self != NULL, "sanity check"); + assert(self->get_threads_hazard_ptr() == NULL, "sanity check"); + assert(self->get_nested_threads_hazard_ptr() == NULL, + "cannot have a nested hazard ptr with a NULL regular hazard ptr"); + + ThreadsList* threads; + + // Stable recording of a hazard ptr for SMR. This code does not use + // locks so its use of the _smr_java_thread_list & _threads_hazard_ptr + // fields is racy relative to code that uses those fields with locks. + // OrderAccess and Atomic functions are used to deal with those races. + // + while (true) { + threads = get_smr_java_thread_list(); + + // Publish a tagged hazard ptr to denote that the hazard ptr is not + // yet verified as being stable. Due to the fence after the hazard + // ptr write, it will be sequentially consistent w.r.t. the + // sequentially consistent writes of the ThreadsList, even on + // non-multiple copy atomic machines where stores can be observed + // in different order from different observer threads. + ThreadsList* unverified_threads = Thread::tag_hazard_ptr(threads); + self->set_threads_hazard_ptr(unverified_threads); + + // If _smr_java_thread_list has changed, we have lost a race with + // Threads::add() or Threads::remove() and have to try again. + if (get_smr_java_thread_list() != threads) { + continue; + } + + // We try to remove the tag which will verify the hazard ptr as + // being stable. This exchange can race with a scanning thread + // which might invalidate the tagged hazard ptr to keep it from + // being followed to access JavaThread ptrs. If we lose the race, + // we simply retry. If we win the race, then the stable hazard + // ptr is officially published. + if (self->cmpxchg_threads_hazard_ptr(threads, unverified_threads) == unverified_threads) { + break; + } + } + + // A stable hazard ptr has been published letting other threads know + // that the ThreadsList and the JavaThreads reachable from this list + // are protected and hence they should not be deleted until everyone + // agrees it is safe to do so. + + return threads; +} + +// Acquire a nested stable ThreadsList; this is rare so it uses +// Threads_lock. +// +ThreadsList *Threads::acquire_stable_list_nested_path(Thread *self) { + assert(self != NULL, "sanity check"); + assert(self->get_threads_hazard_ptr() != NULL, + "cannot have a NULL regular hazard ptr when acquiring a nested hazard ptr"); + + // The thread already has a hazard ptr (ThreadsList ref) so we need + // to create a nested ThreadsListHandle with the current ThreadsList + // since it might be different than our current hazard ptr. The need + // for a nested ThreadsListHandle is rare so we do this while holding + // the Threads_lock so we don't race with the scanning code; the code + // is so much simpler this way. + + NestedThreadsList* node; + { + // Only grab the Threads_lock if we don't already own it. + MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock); + node = new NestedThreadsList(get_smr_java_thread_list()); + // We insert at the front of the list to match up with the delete + // in release_stable_list(). + node->set_next(self->get_nested_threads_hazard_ptr()); + self->set_nested_threads_hazard_ptr(node); + if (EnableThreadSMRStatistics) { + self->inc_nested_threads_hazard_ptr_cnt(); + if (self->nested_threads_hazard_ptr_cnt() > _smr_nested_thread_list_max) { + _smr_nested_thread_list_max = self->nested_threads_hazard_ptr_cnt(); + } + } + } + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::acquire_stable_list: add NestedThreadsList node containing ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(node->t_list())); + + return node->t_list(); +} + +inline void Threads::add_smr_deleted_thread_times(uint add_value) { + Atomic::add(add_value, &_smr_deleted_thread_times); +} + +inline void Threads::inc_smr_deleted_thread_cnt() { + Atomic::inc(&_smr_deleted_thread_cnt); +} + +// Release a stable ThreadsList. +// +void Threads::release_stable_list(Thread *self) { + assert(self != NULL, "sanity check"); + // release_stable_list_nested_path() will grab the Threads_lock + // so let's make sure the ThreadsListHandle is in a safe place. + debug_only(if (StrictSafepointChecks) self->check_for_valid_safepoint_state(/* potential_vm_operation */ false);) + + if (self->get_nested_threads_hazard_ptr() == NULL) { + // The typical case is first. + release_stable_list_fast_path(self); + return; + } + + // The nested case is rare. + release_stable_list_nested_path(self); +} + +// Fast path way to release a stable ThreadsList. The release portion +// is lock-free, but the wake up portion is not. +// +void Threads::release_stable_list_fast_path(Thread *self) { + assert(self != NULL, "sanity check"); + assert(self->get_threads_hazard_ptr() != NULL, "sanity check"); + assert(self->get_nested_threads_hazard_ptr() == NULL, + "cannot have a nested hazard ptr when releasing a regular hazard ptr"); + + // After releasing the hazard ptr, other threads may go ahead and + // free up some memory temporarily used by a ThreadsList snapshot. + self->set_threads_hazard_ptr(NULL); + + // We use double-check locking to reduce traffic on the system + // wide smr_delete_lock. + if (Threads::smr_delete_notify()) { + // An exiting thread might be waiting in smr_delete(); we need to + // check with smr_delete_lock to be sure. + release_stable_list_wake_up((char *) "regular hazard ptr"); + } +} + +// Release a nested stable ThreadsList; this is rare so it uses +// Threads_lock. +// +void Threads::release_stable_list_nested_path(Thread *self) { + assert(self != NULL, "sanity check"); + assert(self->get_nested_threads_hazard_ptr() != NULL, "sanity check"); + assert(self->get_threads_hazard_ptr() != NULL, + "must have a regular hazard ptr to have nested hazard ptrs"); + + // We have a nested ThreadsListHandle so we have to release it first. + // The need for a nested ThreadsListHandle is rare so we do this while + // holding the Threads_lock so we don't race with the scanning code; + // the code is so much simpler this way. + + NestedThreadsList *node; + { + // Only grab the Threads_lock if we don't already own it. + MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock); + // We remove from the front of the list to match up with the insert + // in acquire_stable_list(). + node = self->get_nested_threads_hazard_ptr(); + self->set_nested_threads_hazard_ptr(node->next()); + if (EnableThreadSMRStatistics) { + self->dec_nested_threads_hazard_ptr_cnt(); + } + } + + // An exiting thread might be waiting in smr_delete(); we need to + // check with smr_delete_lock to be sure. + release_stable_list_wake_up((char *) "nested hazard ptr"); + + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::release_stable_list: delete NestedThreadsList node containing ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(node->t_list())); + + delete node; +} + +// Wake up portion of the release stable ThreadsList protocol; +// uses the smr_delete_lock(). +// +void Threads::release_stable_list_wake_up(char *log_str) { + assert(log_str != NULL, "sanity check"); + + // Note: smr_delete_lock is held in smr_delete() for the entire + // hazard ptr search so that we do not lose this notify() if + // the exiting thread has to wait. That code path also holds + // Threads_lock (which was grabbed before smr_delete_lock) so that + // threads_do() can be called. This means the system can't start a + // safepoint which means this thread can't take too long to get to + // a safepoint because of being blocked on smr_delete_lock. + // + MonitorLockerEx ml(Threads::smr_delete_lock(), Monitor::_no_safepoint_check_flag); + if (Threads::smr_delete_notify()) { + // Notify any exiting JavaThreads that are waiting in smr_delete() + // that we've released a ThreadsList. + ml.notify_all(); + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::release_stable_list notified %s", os::current_thread_id(), log_str); + } +} + +inline void Threads::update_smr_deleted_thread_time_max(uint new_value) { + while (true) { + uint cur_value = _smr_deleted_thread_time_max; + if (new_value <= cur_value) { + // No need to update max value so we're done. + break; + } + if (Atomic::cmpxchg(new_value, &_smr_deleted_thread_time_max, cur_value) == cur_value) { + // Updated max value so we're done. Otherwise try it all again. + break; + } + } +} + +inline ThreadsList* Threads::xchg_smr_java_thread_list(ThreadsList* new_list) { + return (ThreadsList*)Atomic::xchg(new_list, &_smr_java_thread_list); +} + void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { TraceTime timer("Initialize java.lang classes", TRACETIME_LOG(Info, startuptime)); @@ -3616,7 +4082,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { if (!main_thread->set_as_starting_thread()) { vm_shutdown_during_initialization( "Failed necessary internal allocation. Out of swap space"); - delete main_thread; + main_thread->smr_delete(); *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again return JNI_ENOMEM; } @@ -3631,7 +4097,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // Initialize global modules jint status = init_globals(); if (status != JNI_OK) { - delete main_thread; + main_thread->smr_delete(); *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again return status; } @@ -4037,23 +4503,6 @@ void Threads::create_vm_init_libraries() { } } -JavaThread* Threads::find_java_thread_from_java_tid(jlong java_tid) { - assert(Threads_lock->owned_by_self(), "Must hold Threads_lock"); - - JavaThread* java_thread = NULL; - // Sequential search for now. Need to do better optimization later. - for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) { - oop tobj = thread->threadObj(); - if (!thread->is_exiting() && - tobj != NULL && - java_tid == java_lang_Thread::thread_id(tobj)) { - java_thread = thread; - break; - } - } - return java_thread; -} - // Last thread running calls java.lang.Shutdown.shutdown() void JavaThread::invoke_shutdown_hooks() { @@ -4179,6 +4628,11 @@ bool Threads::destroy_vm() { notify_vm_shutdown(); + // We are after VM_Exit::set_vm_exited() so we can't call + // thread->smr_delete() or we will block on the Threads_lock. + // Deleting the shutdown thread here is safe because another + // JavaThread cannot have an active ThreadsListHandle for + // this JavaThread. delete thread; #if INCLUDE_JVMCI @@ -4212,6 +4666,501 @@ jboolean Threads::is_supported_jni_version(jint version) { return JNI_FALSE; } +// Hash table of pointers found by a scan. Used for collecting hazard +// pointers (ThreadsList references). Also used for collecting JavaThreads +// that are indirectly referenced by hazard ptrs. An instance of this +// class only contains one type of pointer. +// +class ThreadScanHashtable : public CHeapObj { + private: + static bool ptr_equals(void * const& s1, void * const& s2) { + return s1 == s2; + } + + static unsigned int ptr_hash(void * const& s1) { + // 2654435761 = 2^32 * Phi (golden ratio) + return (unsigned int)(((uint32_t)(uintptr_t)s1) * 2654435761u); + } + + int _table_size; + // ResourceHashtable SIZE is specified at compile time so our + // dynamic _table_size is unused for now; 1031 is the first prime + // after 1024. + typedef ResourceHashtable PtrTable; + PtrTable * _ptrs; + + public: + // ResourceHashtable is passed to various functions and populated in + // different places so we allocate it using C_HEAP to make it immune + // from any ResourceMarks that happen to be in the code paths. + ThreadScanHashtable(int table_size) : _table_size(table_size), _ptrs(new (ResourceObj::C_HEAP, mtThread) PtrTable()) {} + + ~ThreadScanHashtable() { delete _ptrs; } + + bool has_entry(void *pointer) { + int *val_ptr = _ptrs->get(pointer); + return val_ptr != NULL && *val_ptr == 1; + } + + void add_entry(void *pointer) { + _ptrs->put(pointer, 1); + } +}; + +// Closure to gather JavaThreads indirectly referenced by hazard ptrs +// (ThreadsList references) into a hash table. This closure handles part 2 +// of the dance - adding all the JavaThreads referenced by the hazard +// pointer (ThreadsList reference) to the hash table. +// +class AddThreadHazardPointerThreadClosure : public ThreadClosure { + private: + ThreadScanHashtable *_table; + + public: + AddThreadHazardPointerThreadClosure(ThreadScanHashtable *table) : _table(table) {} + + virtual void do_thread(Thread *thread) { + if (!_table->has_entry((void*)thread)) { + // The same JavaThread might be on more than one ThreadsList or + // more than one thread might be using the same ThreadsList. In + // either case, we only need a single entry for a JavaThread. + _table->add_entry((void*)thread); + } + } +}; + +// Closure to gather JavaThreads indirectly referenced by hazard ptrs +// (ThreadsList references) into a hash table. This closure handles part 1 +// of the dance - hazard ptr chain walking and dispatch to another +// closure. +// +class ScanHazardPtrGatherProtectedThreadsClosure : public ThreadClosure { + private: + ThreadScanHashtable *_table; + public: + ScanHazardPtrGatherProtectedThreadsClosure(ThreadScanHashtable *table) : _table(table) {} + + virtual void do_thread(Thread *thread) { + assert_locked_or_safepoint(Threads_lock); + + if (thread == NULL) return; + + // This code races with Threads::acquire_stable_list() which is + // lock-free so we have to handle some special situations. + // + ThreadsList *current_list = NULL; + while (true) { + current_list = thread->get_threads_hazard_ptr(); + // No hazard ptr so nothing more to do. + if (current_list == NULL) { + assert(thread->get_nested_threads_hazard_ptr() == NULL, + "cannot have a nested hazard ptr with a NULL regular hazard ptr"); + return; + } + + // If the hazard ptr is verified as stable (since it is not tagged), + // then it is safe to use. + if (!Thread::is_hazard_ptr_tagged(current_list)) break; + + // The hazard ptr is tagged as not yet verified as being stable + // so we are racing with acquire_stable_list(). This exchange + // attempts to invalidate the hazard ptr. If we win the race, + // then we can ignore this unstable hazard ptr and the other + // thread will retry the attempt to publish a stable hazard ptr. + // If we lose the race, then we retry our attempt to look at the + // hazard ptr. + if (thread->cmpxchg_threads_hazard_ptr(NULL, current_list) == current_list) return; + } + + // The current JavaThread has a hazard ptr (ThreadsList reference) + // which might be _smr_java_thread_list or it might be an older + // ThreadsList that has been removed but not freed. In either case, + // the hazard ptr is protecting all the JavaThreads on that + // ThreadsList. + AddThreadHazardPointerThreadClosure add_cl(_table); + current_list->threads_do(&add_cl); + + // Any NestedThreadsLists are also protecting JavaThreads so + // gather those also; the ThreadsLists may be different. + for (NestedThreadsList* node = thread->get_nested_threads_hazard_ptr(); + node != NULL; node = node->next()) { + node->t_list()->threads_do(&add_cl); + } + } +}; + +// Closure to print JavaThreads that have a hazard ptr (ThreadsList +// reference) that contains an indirect reference to a specific JavaThread. +// +class ScanHazardPtrPrintMatchingThreadsClosure : public ThreadClosure { + private: + JavaThread *_thread; + public: + ScanHazardPtrPrintMatchingThreadsClosure(JavaThread *thread) : _thread(thread) {} + + virtual void do_thread(Thread *thread) { + assert_locked_or_safepoint(Threads_lock); + + if (thread == NULL) return; + ThreadsList *current_list = thread->get_threads_hazard_ptr(); + if (current_list == NULL) { + assert(thread->get_nested_threads_hazard_ptr() == NULL, + "cannot have a nested hazard ptr with a NULL regular hazard ptr"); + return; + } + // If the hazard ptr is unverified, then ignore it. + if (Thread::is_hazard_ptr_tagged(current_list)) return; + + // The current JavaThread has a hazard ptr (ThreadsList reference) + // which might be _smr_java_thread_list or it might be an older + // ThreadsList that has been removed but not freed. In either case, + // the hazard ptr is protecting all the JavaThreads on that + // ThreadsList, but we only care about matching a specific JavaThread. + DO_JAVA_THREADS(current_list, p) { + if (p == _thread) { + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread1=" INTPTR_FORMAT " has a hazard pointer for thread2=" INTPTR_FORMAT, os::current_thread_id(), p2i(thread), p2i(_thread)); + break; + } + } + + // Any NestedThreadsLists are also protecting JavaThreads so + // check those also; the ThreadsLists may be different. + for (NestedThreadsList* node = thread->get_nested_threads_hazard_ptr(); + node != NULL; node = node->next()) { + DO_JAVA_THREADS(node->t_list(), p) { + if (p == _thread) { + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread1=" INTPTR_FORMAT " has a nested hazard pointer for thread2=" INTPTR_FORMAT, os::current_thread_id(), p2i(thread), p2i(_thread)); + return; + } + } + } + } +}; + +// Return true if the specified JavaThread is protected by a hazard +// pointer (ThreadsList reference). Otherwise, returns false. +// +bool Threads::is_a_protected_JavaThread(JavaThread *thread) { + assert_locked_or_safepoint(Threads_lock); + + // Hash table size should be first power of two higher than twice + // the length of the Threads list. + int hash_table_size = MIN2(_number_of_threads, 32) << 1; + hash_table_size--; + hash_table_size |= hash_table_size >> 1; + hash_table_size |= hash_table_size >> 2; + hash_table_size |= hash_table_size >> 4; + hash_table_size |= hash_table_size >> 8; + hash_table_size |= hash_table_size >> 16; + hash_table_size++; + + // Gather a hash table of the JavaThreads indirectly referenced by + // hazard ptrs. + ThreadScanHashtable *scan_table = new ThreadScanHashtable(hash_table_size); + ScanHazardPtrGatherProtectedThreadsClosure scan_cl(scan_table); + Threads::threads_do(&scan_cl); + + bool thread_is_protected = false; + if (scan_table->has_entry((void*)thread)) { + thread_is_protected = true; + } + delete scan_table; + return thread_is_protected; +} + +// Safely delete a JavaThread when it is no longer in use by a +// ThreadsListHandle. +// +void Threads::smr_delete(JavaThread *thread) { + assert(!Threads_lock->owned_by_self(), "sanity"); + + bool has_logged_once = false; + elapsedTimer timer; + if (EnableThreadSMRStatistics) { + timer.start(); + } + + while (true) { + { + // No safepoint check because this JavaThread is not on the + // Threads list. + MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); + // Cannot use a MonitorLockerEx helper here because we have + // to drop the Threads_lock first if we wait. + Threads::smr_delete_lock()->lock_without_safepoint_check(); + // Set the smr_delete_notify flag after we grab smr_delete_lock + // and before we scan hazard ptrs because we're doing + // double-check locking in release_stable_list(). + Threads::set_smr_delete_notify(); + + if (!is_a_protected_JavaThread(thread)) { + // This is the common case. + Threads::clear_smr_delete_notify(); + Threads::smr_delete_lock()->unlock(); + break; + } + if (!has_logged_once) { + has_logged_once = true; + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread=" INTPTR_FORMAT " is not deleted.", os::current_thread_id(), p2i(thread)); + if (log_is_enabled(Debug, os, thread)) { + ScanHazardPtrPrintMatchingThreadsClosure scan_cl(thread); + Threads::threads_do(&scan_cl); + } + } + } // We have to drop the Threads_lock to wait or delete the thread + + if (EnableThreadSMRStatistics) { + _smr_delete_lock_wait_cnt++; + if (_smr_delete_lock_wait_cnt > _smr_delete_lock_wait_max) { + _smr_delete_lock_wait_max = _smr_delete_lock_wait_cnt; + } + } + // Wait for a release_stable_list() call before we check again. No + // safepoint check, no timeout, and not as suspend equivalent flag + // because this JavaThread is not on the Threads list. + Threads::smr_delete_lock()->wait(Mutex::_no_safepoint_check_flag, 0, + !Mutex::_as_suspend_equivalent_flag); + if (EnableThreadSMRStatistics) { + _smr_delete_lock_wait_cnt--; + } + + Threads::clear_smr_delete_notify(); + Threads::smr_delete_lock()->unlock(); + // Retry the whole scenario. + } + + if (ThreadLocalHandshakes) { + // The thread is about to be deleted so cancel any handshake. + thread->cancel_handshake(); + } + + delete thread; + if (EnableThreadSMRStatistics) { + timer.stop(); + uint millis = (uint)timer.milliseconds(); + Threads::inc_smr_deleted_thread_cnt(); + Threads::add_smr_deleted_thread_times(millis); + Threads::update_smr_deleted_thread_time_max(millis); + } + + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread=" INTPTR_FORMAT " is deleted.", os::current_thread_id(), p2i(thread)); +} + +bool Threads::smr_delete_notify() { + // Use load_acquire() in order to see any updates to _smr_delete_notify + // earlier than when smr_delete_lock is grabbed. + return (OrderAccess::load_acquire(&_smr_delete_notify) != 0); +} + +// set_smr_delete_notify() and clear_smr_delete_notify() are called +// under the protection of the smr_delete_lock, but we also use an +// Atomic operation to ensure the memory update is seen earlier than +// when the smr_delete_lock is dropped. +// +void Threads::set_smr_delete_notify() { + Atomic::inc(&_smr_delete_notify); +} + +void Threads::clear_smr_delete_notify() { + Atomic::dec(&_smr_delete_notify); +} + +// Closure to gather hazard ptrs (ThreadsList references) into a hash table. +// +class ScanHazardPtrGatherThreadsListClosure : public ThreadClosure { + private: + ThreadScanHashtable *_table; + public: + ScanHazardPtrGatherThreadsListClosure(ThreadScanHashtable *table) : _table(table) {} + + virtual void do_thread(Thread* thread) { + assert_locked_or_safepoint(Threads_lock); + + if (thread == NULL) return; + ThreadsList *threads = thread->get_threads_hazard_ptr(); + if (threads == NULL) { + assert(thread->get_nested_threads_hazard_ptr() == NULL, + "cannot have a nested hazard ptr with a NULL regular hazard ptr"); + return; + } + // In this closure we always ignore the tag that might mark this + // hazard ptr as not yet verified. If we happen to catch an + // unverified hazard ptr that is subsequently discarded (not + // published), then the only side effect is that we might keep a + // to-be-deleted ThreadsList alive a little longer. + threads = Thread::untag_hazard_ptr(threads); + if (!_table->has_entry((void*)threads)) { + _table->add_entry((void*)threads); + } + + // Any NestedThreadsLists are also protecting JavaThreads so + // gather those also; the ThreadsLists may be different. + for (NestedThreadsList* node = thread->get_nested_threads_hazard_ptr(); + node != NULL; node = node->next()) { + threads = node->t_list(); + if (!_table->has_entry((void*)threads)) { + _table->add_entry((void*)threads); + } + } + } +}; + +// Safely free a ThreadsList after a Threads::add() or Threads::remove(). +// The specified ThreadsList may not get deleted during this call if it +// is still in-use (referenced by a hazard ptr). Other ThreadsLists +// in the chain may get deleted by this call if they are no longer in-use. +void Threads::smr_free_list(ThreadsList* threads) { + assert_locked_or_safepoint(Threads_lock); + + threads->set_next_list(_smr_to_delete_list); + _smr_to_delete_list = threads; + if (EnableThreadSMRStatistics) { + _smr_to_delete_list_cnt++; + if (_smr_to_delete_list_cnt > _smr_to_delete_list_max) { + _smr_to_delete_list_max = _smr_to_delete_list_cnt; + } + } + + // Hash table size should be first power of two higher than twice the length of the ThreadsList + int hash_table_size = MIN2(_number_of_threads, 32) << 1; + hash_table_size--; + hash_table_size |= hash_table_size >> 1; + hash_table_size |= hash_table_size >> 2; + hash_table_size |= hash_table_size >> 4; + hash_table_size |= hash_table_size >> 8; + hash_table_size |= hash_table_size >> 16; + hash_table_size++; + + // Gather a hash table of the current hazard ptrs: + ThreadScanHashtable *scan_table = new ThreadScanHashtable(hash_table_size); + ScanHazardPtrGatherThreadsListClosure scan_cl(scan_table); + Threads::threads_do(&scan_cl); + + // Walk through the linked list of pending freeable ThreadsLists + // and free the ones that are not referenced from hazard ptrs. + ThreadsList* current = _smr_to_delete_list; + ThreadsList* prev = NULL; + ThreadsList* next = NULL; + bool threads_is_freed = false; + while (current != NULL) { + next = current->next_list(); + if (!scan_table->has_entry((void*)current)) { + // This ThreadsList is not referenced by a hazard ptr. + if (prev != NULL) { + prev->set_next_list(next); + } + if (_smr_to_delete_list == current) { + _smr_to_delete_list = next; + } + + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_free_list: threads=" INTPTR_FORMAT " is freed.", os::current_thread_id(), p2i(current)); + if (current == threads) threads_is_freed = true; + delete current; + if (EnableThreadSMRStatistics) { + _smr_java_thread_list_free_cnt++; + _smr_to_delete_list_cnt--; + } + } else { + prev = current; + } + current = next; + } + + if (!threads_is_freed) { + // Only report "is not freed" on the original call to + // smr_free_list() for this ThreadsList. + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_free_list: threads=" INTPTR_FORMAT " is not freed.", os::current_thread_id(), p2i(threads)); + } + + delete scan_table; +} + +// Remove a JavaThread from a ThreadsList. The returned ThreadsList is a +// new copy of the specified ThreadsList with the specified JavaThread +// removed. +ThreadsList *ThreadsList::remove_thread(ThreadsList* list, JavaThread* java_thread) { + assert(list->_length > 0, "sanity"); + + uint i = 0; + DO_JAVA_THREADS(list, current) { + if (current == java_thread) { + break; + } + i++; + } + assert(i < list->_length, "did not find JavaThread on the list"); + const uint index = i; + const uint new_length = list->_length - 1; + const uint head_length = index; + const uint tail_length = (new_length >= index) ? (new_length - index) : 0; + ThreadsList *const new_list = new ThreadsList(new_length); + + if (head_length > 0) { + Copy::disjoint_words((HeapWord*)list->_threads, (HeapWord*)new_list->_threads, head_length); + } + if (tail_length > 0) { + Copy::disjoint_words((HeapWord*)list->_threads + index + 1, (HeapWord*)new_list->_threads + index, tail_length); + } + + return new_list; +} + +// Add a JavaThread to a ThreadsList. The returned ThreadsList is a +// new copy of the specified ThreadsList with the specified JavaThread +// appended to the end. +ThreadsList *ThreadsList::add_thread(ThreadsList *list, JavaThread *java_thread) { + const uint index = list->_length; + const uint new_length = index + 1; + const uint head_length = index; + ThreadsList *const new_list = new ThreadsList(new_length); + + if (head_length > 0) { + Copy::disjoint_words((HeapWord*)list->_threads, (HeapWord*)new_list->_threads, head_length); + } + *(JavaThread**)(new_list->_threads + index) = java_thread; + + return new_list; +} + +int ThreadsList::find_index_of_JavaThread(JavaThread *target) { + if (target == NULL) { + return -1; + } + for (uint i = 0; i < length(); i++) { + if (target == thread_at(i)) { + return (int)i; + } + } + return -1; +} + +JavaThread* ThreadsList::find_JavaThread_from_java_tid(jlong java_tid) const { + DO_JAVA_THREADS(this, thread) { + oop tobj = thread->threadObj(); + // Ignore the thread if it hasn't run yet, has exited + // or is starting to exit. + if (tobj != NULL && !thread->is_exiting() && + java_tid == java_lang_Thread::thread_id(tobj)) { + // found a match + return thread; + } + } + return NULL; +} + +bool ThreadsList::includes(const JavaThread * const p) const { + if (p == NULL) { + return false; + } + DO_JAVA_THREADS(this, q) { + if (q == p) { + return true; + } + } + return false; +} void Threads::add(JavaThread* p, bool force_daemon) { // The threads lock must be owned at this point @@ -4222,6 +5171,11 @@ void Threads::add(JavaThread* p, bool force_daemon) { p->initialize_queues(); p->set_next(_thread_list); _thread_list = p; + + // Once a JavaThread is added to the Threads list, smr_delete() has + // to be used to delete it. Otherwise we can just delete it directly. + p->set_on_thread_list(); + _number_of_threads++; oop threadObj = p->threadObj(); bool daemon = true; @@ -4234,6 +5188,20 @@ void Threads::add(JavaThread* p, bool force_daemon) { ThreadService::add_thread(p, daemon); + // Maintain fast thread list + ThreadsList *new_list = ThreadsList::add_thread(get_smr_java_thread_list(), p); + if (EnableThreadSMRStatistics) { + _smr_java_thread_list_alloc_cnt++; + if (new_list->length() > _smr_java_thread_list_max) { + _smr_java_thread_list_max = new_list->length(); + } + } + // Initial _smr_java_thread_list will not generate a "Threads::add" mesg. + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::add: new ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(new_list)); + + ThreadsList *old_list = xchg_smr_java_thread_list(new_list); + smr_free_list(old_list); + // Possible GC point. Events::log(p, "Thread added: " INTPTR_FORMAT, p2i(p)); } @@ -4247,7 +5215,20 @@ void Threads::remove(JavaThread* p) { // that we do not remove thread without safepoint code notice { MutexLocker ml(Threads_lock); - assert(includes(p), "p must be present"); + assert(get_smr_java_thread_list()->includes(p), "p must be present"); + + // Maintain fast thread list + ThreadsList *new_list = ThreadsList::remove_thread(get_smr_java_thread_list(), p); + if (EnableThreadSMRStatistics) { + _smr_java_thread_list_alloc_cnt++; + // This list is smaller so no need to check for a "longest" update. + } + + // Final _smr_java_thread_list will not generate a "Threads::remove" mesg. + log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::remove: new ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(new_list)); + + ThreadsList *old_list = xchg_smr_java_thread_list(new_list); + smr_free_list(old_list); JavaThread* current = _thread_list; JavaThread* prev = NULL; @@ -4262,6 +5243,7 @@ void Threads::remove(JavaThread* p) { } else { _thread_list = p->next(); } + _number_of_threads--; oop threadObj = p->threadObj(); bool daemon = true; @@ -4288,17 +5270,6 @@ void Threads::remove(JavaThread* p) { Events::log(p, "Thread exited: " INTPTR_FORMAT, p2i(p)); } -// Threads_lock must be held when this is called (or must be called during a safepoint) -bool Threads::includes(JavaThread* p) { - assert(Threads_lock->is_locked(), "sanity check"); - ALL_JAVA_THREADS(q) { - if (q == p) { - return true; - } - } - return false; -} - // Operations on the Threads list for GC. These are not explicitly locked, // but the garbage collector must provide a safe context for them to run. // In particular, these things should never be called when the Threads_lock @@ -4411,47 +5382,36 @@ void Threads::deoptimized_wrt_marked_nmethods() { // Get count Java threads that are waiting to enter the specified monitor. -GrowableArray* Threads::get_pending_threads(int count, - address monitor, - bool doLock) { - assert(doLock || SafepointSynchronize::is_at_safepoint(), - "must grab Threads_lock or be at safepoint"); +GrowableArray* Threads::get_pending_threads(ThreadsList * t_list, + int count, + address monitor) { GrowableArray* result = new GrowableArray(count); int i = 0; - { - MutexLockerEx ml(doLock ? Threads_lock : NULL); - ALL_JAVA_THREADS(p) { - if (!p->can_call_java()) continue; + DO_JAVA_THREADS(t_list, p) { + if (!p->can_call_java()) continue; - address pending = (address)p->current_pending_monitor(); - if (pending == monitor) { // found a match - if (i < count) result->append(p); // save the first count matches - i++; - } + address pending = (address)p->current_pending_monitor(); + if (pending == monitor) { // found a match + if (i < count) result->append(p); // save the first count matches + i++; } } + return result; } -JavaThread *Threads::owning_thread_from_monitor_owner(address owner, - bool doLock) { - assert(doLock || - Threads_lock->owned_by_self() || - SafepointSynchronize::is_at_safepoint(), - "must grab Threads_lock or be at safepoint"); - +JavaThread *Threads::owning_thread_from_monitor_owner(ThreadsList * t_list, + address owner) { // NULL owner means not locked so we can skip the search if (owner == NULL) return NULL; - { - MutexLockerEx ml(doLock ? Threads_lock : NULL); - ALL_JAVA_THREADS(p) { - // first, see if owner is the address of a Java thread - if (owner == (address)p) return p; - } + DO_JAVA_THREADS(t_list, p) { + // first, see if owner is the address of a Java thread + if (owner == (address)p) return p; } + // Cannot assert on lack of success here since this function may be // used by code that is trying to report useful problem information // like deadlock detection. @@ -4462,15 +5422,13 @@ JavaThread *Threads::owning_thread_from_monitor_owner(address owner, // Lock Word in the owning Java thread's stack. // JavaThread* the_owner = NULL; - { - MutexLockerEx ml(doLock ? Threads_lock : NULL); - ALL_JAVA_THREADS(q) { - if (q->is_lock_owned(owner)) { - the_owner = q; - break; - } + DO_JAVA_THREADS(t_list, q) { + if (q->is_lock_owned(owner)) { + the_owner = q; + break; } } + // cannot assert on lack of success here; see above comment return the_owner; } @@ -4495,6 +5453,9 @@ void Threads::print_on(outputStream* st, bool print_stacks, } #endif // INCLUDE_SERVICES + print_smr_info_on(st); + st->cr(); + ALL_JAVA_THREADS(p) { ResourceMark rm; p->print_on(st); @@ -4521,9 +5482,105 @@ void Threads::print_on(outputStream* st, bool print_stacks, wt->print_on(st); st->cr(); } + st->flush(); } +// Log Threads class SMR info. +void Threads::log_smr_statistics() { + LogTarget(Info, thread, smr) log; + if (log.is_enabled()) { + LogStream out(log); + print_smr_info_on(&out); + } +} + +// Print Threads class SMR info. +void Threads::print_smr_info_on(outputStream* st) { + // Only grab the Threads_lock if we don't already own it + // and if we are not reporting an error. + MutexLockerEx ml((Threads_lock->owned_by_self() || VMError::is_error_reported()) ? NULL : Threads_lock); + + st->print_cr("Threads class SMR info:"); + st->print_cr("_smr_java_thread_list=" INTPTR_FORMAT ", length=%u, " + "elements={", p2i(_smr_java_thread_list), + _smr_java_thread_list->length()); + print_smr_info_elements_on(st, _smr_java_thread_list); + st->print_cr("}"); + if (_smr_to_delete_list != NULL) { + st->print_cr("_smr_to_delete_list=" INTPTR_FORMAT ", length=%u, " + "elements={", p2i(_smr_to_delete_list), + _smr_to_delete_list->length()); + print_smr_info_elements_on(st, _smr_to_delete_list); + st->print_cr("}"); + for (ThreadsList *t_list = _smr_to_delete_list->next_list(); + t_list != NULL; t_list = t_list->next_list()) { + st->print("next-> " INTPTR_FORMAT ", length=%u, " + "elements={", p2i(t_list), t_list->length()); + print_smr_info_elements_on(st, t_list); + st->print_cr("}"); + } + } + if (!EnableThreadSMRStatistics) { + return; + } + st->print_cr("_smr_java_thread_list_alloc_cnt=" UINT64_FORMAT "," + "_smr_java_thread_list_free_cnt=" UINT64_FORMAT "," + "_smr_java_thread_list_max=%u, " + "_smr_nested_thread_list_max=%u", + _smr_java_thread_list_alloc_cnt, + _smr_java_thread_list_free_cnt, + _smr_java_thread_list_max, + _smr_nested_thread_list_max); + if (_smr_tlh_cnt > 0) { + st->print_cr("_smr_tlh_cnt=%u" + ", _smr_tlh_times=%u" + ", avg_smr_tlh_time=%0.2f" + ", _smr_tlh_time_max=%u", + _smr_tlh_cnt, _smr_tlh_times, + ((double) _smr_tlh_times / _smr_tlh_cnt), + _smr_tlh_time_max); + } + if (_smr_deleted_thread_cnt > 0) { + st->print_cr("_smr_deleted_thread_cnt=%u" + ", _smr_deleted_thread_times=%u" + ", avg_smr_deleted_thread_time=%0.2f" + ", _smr_deleted_thread_time_max=%u", + _smr_deleted_thread_cnt, _smr_deleted_thread_times, + ((double) _smr_deleted_thread_times / _smr_deleted_thread_cnt), + _smr_deleted_thread_time_max); + } + st->print_cr("_smr_delete_lock_wait_cnt=%u, _smr_delete_lock_wait_max=%u", + _smr_delete_lock_wait_cnt, _smr_delete_lock_wait_max); + st->print_cr("_smr_to_delete_list_cnt=%u, _smr_to_delete_list_max=%u", + _smr_to_delete_list_cnt, _smr_to_delete_list_max); +} + +// Print ThreadsList elements (4 per line). +void Threads::print_smr_info_elements_on(outputStream* st, + ThreadsList* t_list) { + uint cnt = 0; + JavaThreadIterator jti(t_list); + for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) { + st->print(INTPTR_FORMAT, p2i(jt)); + if (cnt < t_list->length() - 1) { + // Separate with comma or comma-space except for the last one. + if (((cnt + 1) % 4) == 0) { + // Four INTPTR_FORMAT fit on an 80 column line so end the + // current line with just a comma. + st->print_cr(","); + } else { + // Not the last one on the current line so use comma-space: + st->print(", "); + } + } else { + // Last one so just end the current line. + st->cr(); + } + cnt++; + } +} + void Threads::print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, int buflen, bool* found_current) { if (this_thread != NULL) { @@ -4560,6 +5617,9 @@ class PrintOnErrorClosure : public ThreadClosure { // memory (even in resource area), it might deadlock the error handler. void Threads::print_on_error(outputStream* st, Thread* current, char* buf, int buflen) { + print_smr_info_on(st); + st->cr(); + bool found_current = false; st->print_cr("Java Threads: ( => current thread )"); ALL_JAVA_THREADS(thread) { @@ -4581,6 +5641,7 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf, st->cr(); } st->cr(); + st->print_cr("Threads with active compile tasks:"); print_threads_compiling(st, buf, buflen); } diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 65fa5aae1c5..db1d465c751 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -57,6 +57,8 @@ #endif class ThreadSafepointState; +class ThreadsList; +class NestedThreadsList; class JvmtiThreadState; class JvmtiGetLoadedClassesClosure; @@ -101,6 +103,7 @@ class WorkerThread; // - WatcherThread class Thread: public ThreadShadow { + friend class Threads; friend class VMStructs; friend class JVMCIVMStructs; private: @@ -118,6 +121,47 @@ class Thread: public ThreadShadow { protected: // Support for forcing alignment of thread objects for biased locking void* _real_malloc_address; + // JavaThread lifecycle support: + friend class ScanHazardPtrGatherProtectedThreadsClosure; + friend class ScanHazardPtrGatherThreadsListClosure; + friend class ScanHazardPtrPrintMatchingThreadsClosure; + friend class ThreadsListHandle; + friend class ThreadsListSetter; + ThreadsList* volatile _threads_hazard_ptr; + ThreadsList* cmpxchg_threads_hazard_ptr(ThreadsList* exchange_value, ThreadsList* compare_value); + ThreadsList* get_threads_hazard_ptr(); + void set_threads_hazard_ptr(ThreadsList* new_list); + static bool is_hazard_ptr_tagged(ThreadsList* list) { + return (intptr_t(list) & intptr_t(1)) == intptr_t(1); + } + static ThreadsList* tag_hazard_ptr(ThreadsList* list) { + return (ThreadsList*)(intptr_t(list) | intptr_t(1)); + } + static ThreadsList* untag_hazard_ptr(ThreadsList* list) { + return (ThreadsList*)(intptr_t(list) & ~intptr_t(1)); + } + NestedThreadsList* _nested_threads_hazard_ptr; + NestedThreadsList* get_nested_threads_hazard_ptr() { + return _nested_threads_hazard_ptr; + } + void set_nested_threads_hazard_ptr(NestedThreadsList* value) { + assert(Threads_lock->owned_by_self(), + "must own Threads_lock for _nested_threads_hazard_ptr to be valid."); + _nested_threads_hazard_ptr = value; + } + // This field is enabled via -XX:+EnableThreadSMRStatistics: + uint _nested_threads_hazard_ptr_cnt; + void dec_nested_threads_hazard_ptr_cnt() { + assert(_nested_threads_hazard_ptr_cnt != 0, "mismatched {dec,inc}_nested_threads_hazard_ptr_cnt()"); + _nested_threads_hazard_ptr_cnt--; + } + void inc_nested_threads_hazard_ptr_cnt() { + _nested_threads_hazard_ptr_cnt++; + } + uint nested_threads_hazard_ptr_cnt() { + return _nested_threads_hazard_ptr_cnt; + } + public: void* operator new(size_t size) throw() { return allocate(size, true); } void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { @@ -359,6 +403,9 @@ class Thread: public ThreadShadow { static inline Thread* current_or_null_safe(); // Common thread operations +#ifdef ASSERT + static void check_for_dangling_thread_pointer(Thread *thread); +#endif static void set_priority(Thread* thread, ThreadPriority priority); static ThreadPriority get_priority(const Thread* const thread); static void start(Thread* thread); @@ -576,6 +623,7 @@ protected: // Printing virtual void print_on(outputStream* st) const; + virtual void print_nested_threads_hazard_ptrs_on(outputStream* st) const; void print() const { print_on(tty); } virtual void print_on_error(outputStream* st, char* buf, int buflen) const; void print_value_on(outputStream* st) const; @@ -798,6 +846,7 @@ class JavaThread: public Thread { friend class WhiteBox; private: JavaThread* _next; // The next thread in the Threads list + bool _on_thread_list; // Is set when this JavaThread is added to the Threads list oop _threadObj; // The Java level thread object #ifdef ASSERT @@ -1125,15 +1174,23 @@ class JavaThread: public Thread { void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; } bool is_at_poll_safepoint() { return _safepoint_state->is_at_poll_safepoint(); } + // JavaThread termination and lifecycle support: + void smr_delete(); + bool on_thread_list() const { return _on_thread_list; } + void set_on_thread_list() { _on_thread_list = true; } + // thread has called JavaThread::exit() or is terminated - bool is_exiting() { return _terminated == _thread_exiting || is_terminated(); } + bool is_exiting() const; // thread is terminated (no longer on the threads list); we compare // against the two non-terminated values so that a freed JavaThread // will also be considered terminated. - bool is_terminated() { return _terminated != _not_terminated && _terminated != _thread_exiting; } - void set_terminated(TerminatedTypes t) { _terminated = t; } + bool check_is_terminated(TerminatedTypes l_terminated) const { + return l_terminated != _not_terminated && l_terminated != _thread_exiting; + } + bool is_terminated() const; + void set_terminated(TerminatedTypes t); // special for Threads::remove() which is static: - void set_terminated_value() { _terminated = _thread_terminated; } + void set_terminated_value(); void block_if_vm_exited(); bool doing_unsafe_access() { return _doing_unsafe_access; } @@ -1220,6 +1277,9 @@ class JavaThread: public Thread { // via the appropriate -XX options. bool wait_for_ext_suspend_completion(int count, int delay, uint32_t *bits); + // test for suspend - most (all?) of these should go away + bool is_thread_fully_suspended(bool wait_for_suspend, uint32_t *bits); + inline void set_external_suspend(); inline void clear_external_suspend(); @@ -2066,28 +2126,84 @@ inline CompilerThread* CompilerThread::current() { class Threads: AllStatic { friend class VMStructs; private: - static JavaThread* _thread_list; - static int _number_of_threads; - static int _number_of_non_daemon_threads; - static int _return_code; - static int _thread_claim_parity; + // Safe Memory Reclamation (SMR) support: + // The coordination between Threads::release_stable_list() and + // Threads::smr_delete() uses the smr_delete_lock in order to + // reduce the traffic on the Threads_lock. + static Monitor* _smr_delete_lock; + // The '_cnt', '_max' and '_times" fields are enabled via + // -XX:+EnableThreadSMRStatistics (see thread.cpp for a + // description about each field): + static uint _smr_delete_lock_wait_cnt; + static uint _smr_delete_lock_wait_max; + // The smr_delete_notify flag is used for proper double-check + // locking in order to reduce the traffic on the smr_delete_lock. + static volatile uint _smr_delete_notify; + static volatile uint _smr_deleted_thread_cnt; + static volatile uint _smr_deleted_thread_time_max; + static volatile uint _smr_deleted_thread_times; + static ThreadsList* volatile _smr_java_thread_list; + static uint64_t _smr_java_thread_list_alloc_cnt; + static uint64_t _smr_java_thread_list_free_cnt; + static uint _smr_java_thread_list_max; + static uint _smr_nested_thread_list_max; + static volatile uint _smr_tlh_cnt; + static volatile uint _smr_tlh_time_max; + static volatile uint _smr_tlh_times; + static ThreadsList* _smr_to_delete_list; + static uint _smr_to_delete_list_cnt; + static uint _smr_to_delete_list_max; + + static JavaThread* _thread_list; + static int _number_of_threads; + static int _number_of_non_daemon_threads; + static int _return_code; + static int _thread_claim_parity; #ifdef ASSERT - static bool _vm_complete; + static bool _vm_complete; #endif static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS); static void initialize_jsr292_core_classes(TRAPS); + + static ThreadsList *acquire_stable_list_fast_path(Thread *self); + static ThreadsList *acquire_stable_list_nested_path(Thread *self); + static void add_smr_deleted_thread_times(uint add_value); + static void clear_smr_delete_notify(); + static ThreadsList* get_smr_java_thread_list(); + static void inc_smr_deleted_thread_cnt(); + static void release_stable_list_fast_path(Thread *self); + static void release_stable_list_nested_path(Thread *self); + static void release_stable_list_wake_up(char *log_str); + static void set_smr_delete_notify(); + static Monitor* smr_delete_lock() { return _smr_delete_lock; } + static bool smr_delete_notify(); + static void smr_free_list(ThreadsList* threads); + static void update_smr_deleted_thread_time_max(uint new_value); + static ThreadsList* xchg_smr_java_thread_list(ThreadsList* new_list); + public: // Thread management // force_daemon is a concession to JNI, where we may need to add a // thread to the thread list before allocating its thread object static void add(JavaThread* p, bool force_daemon = false); static void remove(JavaThread* p); - static bool includes(JavaThread* p); - static JavaThread* first() { return _thread_list; } static void threads_do(ThreadClosure* tc); static void possibly_parallel_threads_do(bool is_par, ThreadClosure* tc); + // SMR support: + static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter); + static void release_stable_list(Thread *self); + static bool is_a_protected_JavaThread(JavaThread *thread); + static bool is_a_protected_JavaThread_with_lock(JavaThread *thread) { + MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock); + return is_a_protected_JavaThread(thread); + } + static void smr_delete(JavaThread *thread); + static void inc_smr_tlh_cnt(); + static void update_smr_tlh_time_max(uint new_value); + static void add_smr_tlh_times(uint add_value); + // Initializes the vm and creates the vm thread static jint create_vm(JavaVMInitArgs* args, bool* canTryAgain); static void convert_vm_init_libraries_to_agents(); @@ -2148,7 +2264,10 @@ class Threads: AllStatic { // Verification static void verify(); + static void log_smr_statistics(); static void print_on(outputStream* st, bool print_stacks, bool internal_format, bool print_concurrent_locks); + static void print_smr_info_on(outputStream* st); + static void print_smr_info_elements_on(outputStream* st, ThreadsList* t_list); static void print(bool print_stacks, bool internal_format) { // this function is only used by debug.cpp print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */); @@ -2158,17 +2277,13 @@ class Threads: AllStatic { int buflen, bool* found_current); static void print_threads_compiling(outputStream* st, char* buf, int buflen); - // Get Java threads that are waiting to enter a monitor. If doLock - // is true, then Threads_lock is grabbed as needed. Otherwise, the - // VM needs to be at a safepoint. - static GrowableArray* get_pending_threads(int count, - address monitor, bool doLock); + // Get Java threads that are waiting to enter a monitor. + static GrowableArray* get_pending_threads(ThreadsList * t_list, + int count, address monitor); - // Get owning Java thread from the monitor's owner field. If doLock - // is true, then Threads_lock is grabbed as needed. Otherwise, the - // VM needs to be at a safepoint. - static JavaThread *owning_thread_from_monitor_owner(address owner, - bool doLock); + // Get owning Java thread from the monitor's owner field. + static JavaThread *owning_thread_from_monitor_owner(ThreadsList * t_list, + address owner); // Number of threads on the active threads list static int number_of_threads() { return _number_of_threads; } @@ -2177,9 +2292,6 @@ class Threads: AllStatic { // Deoptimizes all frames tied to marked nmethods static void deoptimized_wrt_marked_nmethods(); - - static JavaThread* find_java_thread_from_java_tid(jlong java_tid); - }; diff --git a/src/hotspot/share/runtime/thread.inline.hpp b/src/hotspot/share/runtime/thread.inline.hpp index 5a664953b9a..3821d9317bf 100644 --- a/src/hotspot/share/runtime/thread.inline.hpp +++ b/src/hotspot/share/runtime/thread.inline.hpp @@ -25,13 +25,10 @@ #ifndef SHARE_VM_RUNTIME_THREAD_INLINE_HPP #define SHARE_VM_RUNTIME_THREAD_INLINE_HPP -#define SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE - #include "runtime/atomic.hpp" #include "runtime/os.inline.hpp" #include "runtime/thread.hpp" - -#undef SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE +#include "runtime/threadSMR.hpp" inline void Thread::set_suspend_flag(SuspendFlags f) { assert(sizeof(jint) == sizeof(_suspend_flags), "size mismatch"); @@ -89,6 +86,18 @@ inline jlong Thread::cooked_allocated_bytes() { return allocated_bytes; } +inline ThreadsList* Thread::cmpxchg_threads_hazard_ptr(ThreadsList* exchange_value, ThreadsList* compare_value) { + return (ThreadsList*)Atomic::cmpxchg(exchange_value, &_threads_hazard_ptr, compare_value); +} + +inline ThreadsList* Thread::get_threads_hazard_ptr() { + return (ThreadsList*)OrderAccess::load_acquire(&_threads_hazard_ptr); +} + +inline void Thread::set_threads_hazard_ptr(ThreadsList* new_list) { + OrderAccess::release_store_fence(&_threads_hazard_ptr, new_list); +} + inline void JavaThread::set_ext_suspended() { set_suspend_flag (_ext_suspended); } @@ -176,4 +185,53 @@ inline volatile void* JavaThread::get_polling_page() { return OrderAccess::load_acquire(polling_page_addr()); } +inline bool JavaThread::is_exiting() const { + // Use load-acquire so that setting of _terminated by + // JavaThread::exit() is seen more quickly. + TerminatedTypes l_terminated = (TerminatedTypes) + OrderAccess::load_acquire((volatile jint *) &_terminated); + return l_terminated == _thread_exiting || check_is_terminated(l_terminated); +} + +inline bool JavaThread::is_terminated() const { + // Use load-acquire so that setting of _terminated by + // JavaThread::exit() is seen more quickly. + TerminatedTypes l_terminated = (TerminatedTypes) + OrderAccess::load_acquire((volatile jint *) &_terminated); + return check_is_terminated(l_terminated); +} + +inline void JavaThread::set_terminated(TerminatedTypes t) { + // use release-store so the setting of _terminated is seen more quickly + OrderAccess::release_store((volatile jint *) &_terminated, (jint) t); +} + +// special for Threads::remove() which is static: +inline void JavaThread::set_terminated_value() { + // use release-store so the setting of _terminated is seen more quickly + OrderAccess::release_store((volatile jint *) &_terminated, (jint) _thread_terminated); +} + +inline void Threads::add_smr_tlh_times(uint add_value) { + Atomic::add(add_value, &_smr_tlh_times); +} + +inline void Threads::inc_smr_tlh_cnt() { + Atomic::inc(&_smr_tlh_cnt); +} + +inline void Threads::update_smr_tlh_time_max(uint new_value) { + while (true) { + uint cur_value = _smr_tlh_time_max; + if (new_value <= cur_value) { + // No need to update max value so we're done. + break; + } + if (Atomic::cmpxchg(new_value, &_smr_tlh_time_max, cur_value) == cur_value) { + // Updated max value so we're done. Otherwise try it all again. + break; + } + } +} + #endif // SHARE_VM_RUNTIME_THREAD_INLINE_HPP diff --git a/src/hotspot/share/runtime/threadSMR.cpp b/src/hotspot/share/runtime/threadSMR.cpp new file mode 100644 index 00000000000..82ecc2590eb --- /dev/null +++ b/src/hotspot/share/runtime/threadSMR.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017, 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 "memory/allocation.inline.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" +#include "services/threadService.hpp" + +// 'entries + 1' so we always have at least one entry. +ThreadsList::ThreadsList(int entries) : _length(entries), _threads(NEW_C_HEAP_ARRAY(JavaThread*, entries + 1, mtThread)), _next_list(NULL) { + *(JavaThread**)(_threads + entries) = NULL; // Make sure the extra entry is NULL. +} + +ThreadsList::~ThreadsList() { + FREE_C_HEAP_ARRAY(JavaThread*, _threads); +} + +ThreadsListSetter::~ThreadsListSetter() { + if (_target_needs_release) { + // The hazard ptr in the target needs to be released. + Threads::release_stable_list(_target); + } +} + +void ThreadsListSetter::set() { + assert(_target->get_threads_hazard_ptr() == NULL, "hazard ptr should not already be set"); + (void) Threads::acquire_stable_list(_target, /* is_ThreadsListSetter */ true); + _target_needs_release = true; +} + +ThreadsListHandle::ThreadsListHandle(Thread *self) : _list(Threads::acquire_stable_list(self, /* is_ThreadsListSetter */ false)), _self(self) { + assert(self == Thread::current(), "sanity check"); + if (EnableThreadSMRStatistics) { + _timer.start(); + } +} + +ThreadsListHandle::~ThreadsListHandle() { + Threads::release_stable_list(_self); + if (EnableThreadSMRStatistics) { + _timer.stop(); + uint millis = (uint)_timer.milliseconds(); + Threads::inc_smr_tlh_cnt(); + Threads::add_smr_tlh_times(millis); + Threads::update_smr_tlh_time_max(millis); + } +} + +// Convert an internal thread reference to a JavaThread found on the +// associated ThreadsList. This ThreadsListHandle "protects" the +// returned JavaThread *. +// +// If thread_oop_p is not NULL, then the caller wants to use the oop +// after this call so the oop is returned. On success, *jt_pp is set +// to the converted JavaThread * and true is returned. On error, +// returns false. +// +bool ThreadsListHandle::cv_internal_thread_to_JavaThread(jobject jthread, + JavaThread ** jt_pp, + oop * thread_oop_p) { + assert(this->list() != NULL, "must have a ThreadsList"); + assert(jt_pp != NULL, "must have a return JavaThread pointer"); + // thread_oop_p is optional so no assert() + + // The JVM_* interfaces don't allow a NULL thread parameter; JVM/TI + // allows a NULL thread parameter to signify "current thread" which + // allows us to avoid calling cv_external_thread_to_JavaThread(). + // The JVM_* interfaces have no such leeway. + + oop thread_oop = JNIHandles::resolve_non_null(jthread); + // Looks like an oop at this point. + if (thread_oop_p != NULL) { + // Return the oop to the caller; the caller may still want + // the oop even if this function returns false. + *thread_oop_p = thread_oop; + } + + JavaThread *java_thread = java_lang_Thread::thread(thread_oop); + if (java_thread == NULL) { + // The java.lang.Thread does not contain a JavaThread * so it has + // not yet run or it has died. + return false; + } + // Looks like a live JavaThread at this point. + + if (java_thread != JavaThread::current()) { + // jthread is not for the current JavaThread so have to verify + // the JavaThread * against the ThreadsList. + if (EnableThreadSMRExtraValidityChecks && !includes(java_thread)) { + // Not on the JavaThreads list so it is not alive. + return false; + } + } + + // Return a live JavaThread that is "protected" by the + // ThreadsListHandle in the caller. + *jt_pp = java_thread; + return true; +} diff --git a/src/hotspot/share/runtime/threadSMR.hpp b/src/hotspot/share/runtime/threadSMR.hpp new file mode 100644 index 00000000000..1e177b7f435 --- /dev/null +++ b/src/hotspot/share/runtime/threadSMR.hpp @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2017, 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_VM_RUNTIME_THREADSMR_HPP +#define SHARE_VM_RUNTIME_THREADSMR_HPP + +#include "memory/allocation.hpp" +#include "runtime/timer.hpp" + +// Thread Safe Memory Reclamation (Thread-SMR) support. +// +// ThreadsListHandles are used to safely perform operations on one or more +// threads without the risk of the thread or threads exiting during the +// operation. It is no longer necessary to hold the Threads_lock to safely +// perform an operation on a target thread. +// +// There are several different ways to refer to java.lang.Thread objects +// so we have a few ways to get a protected JavaThread *: +// +// JNI jobject example: +// jobject jthread = ...; +// : +// ThreadsListHandle tlh; +// JavaThread* jt = NULL; +// bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &jt, NULL); +// if (is_alive) { +// : // do stuff with 'jt'... +// } +// +// JVM/TI jthread example: +// jthread thread = ...; +// : +// JavaThread* jt = NULL; +// ThreadsListHandle tlh; +// jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &jt, NULL); +// if (err != JVMTI_ERROR_NONE) { +// return err; +// } +// : // do stuff with 'jt'... +// +// JVM/TI oop example (this one should be very rare): +// oop thread_obj = ...; +// : +// JavaThread *jt = NULL; +// ThreadsListHandle tlh; +// jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &jt); +// if (err != JVMTI_ERROR_NONE) { +// return err; +// } +// : // do stuff with 'jt'... +// +// A JavaThread * that is included in the ThreadsList that is held by +// a ThreadsListHandle is protected as long as the ThreadsListHandle +// remains in scope. The target JavaThread * may have logically exited, +// but that target JavaThread * will not be deleted until it is no +// longer protected by a ThreadsListHandle. + + +// A fast list of JavaThreads. +// +class ThreadsList : public CHeapObj { + friend class ScanHazardPtrGatherProtectedThreadsClosure; + friend class Threads; + + const uint _length; + ThreadsList* _next_list; + JavaThread *const *const _threads; + + template + void threads_do_dispatch(T *cl, JavaThread *const thread) const; + + ThreadsList *next_list() const { return _next_list; } + void set_next_list(ThreadsList *list) { _next_list = list; } + +public: + ThreadsList(int entries); + ~ThreadsList(); + + template + void threads_do(T *cl) const; + + uint length() const { return _length; } + + JavaThread *const thread_at(uint i) const { return _threads[i]; } + + JavaThread *const *threads() const { return _threads; } + + // Returns -1 if target is not found. + int find_index_of_JavaThread(JavaThread* target); + JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const; + bool includes(const JavaThread * const p) const; + + static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread); + static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread); +}; + +// Linked list of ThreadsLists to support nested ThreadsListHandles. +class NestedThreadsList : public CHeapObj { + ThreadsList*const _t_list; + NestedThreadsList* _next; + +public: + NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) { + assert(Threads_lock->owned_by_self(), + "must own Threads_lock for saved t_list to be valid."); + } + + ThreadsList* t_list() { return _t_list; } + NestedThreadsList* next() { return _next; } + void set_next(NestedThreadsList* value) { _next = value; } +}; + +// A helper to optionally set the hazard ptr in ourself. This helper can +// be used by ourself or by another thread. If the hazard ptr is set(), +// then the destructor will release it. +// +class ThreadsListSetter : public StackObj { +private: + bool _target_needs_release; // needs release only when set() + Thread * _target; + +public: + ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) { + } + ~ThreadsListSetter(); + ThreadsList* list(); + void set(); + bool target_needs_release() { return _target_needs_release; } +}; + +// This stack allocated ThreadsListHandle keeps all JavaThreads in the +// ThreadsList from being deleted until it is safe. +// +class ThreadsListHandle : public StackObj { + ThreadsList * _list; + Thread *const _self; + elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics. + +public: + ThreadsListHandle(Thread *self = Thread::current()); + ~ThreadsListHandle(); + + ThreadsList *list() const { + return _list; + } + + template + void threads_do(T *cl) const { + return _list->threads_do(cl); + } + + bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); + + bool includes(JavaThread* p) { + return _list->includes(p); + } + + uint length() const { + return _list->length(); + } +}; + +// This stack allocated JavaThreadIterator is used to walk the +// specified ThreadsList using the following style: +// +// JavaThreadIterator jti(t_list); +// for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) { +// ... +// } +// +class JavaThreadIterator : public StackObj { + ThreadsList * _list; + uint _index; + +public: + JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) { + assert(list != NULL, "ThreadsList must not be NULL."); + } + + JavaThread *first() { + _index = 0; + return _list->thread_at(_index); + } + + uint length() const { + return _list->length(); + } + + ThreadsList *list() const { + return _list; + } + + JavaThread *next() { + if (++_index >= length()) { + return NULL; + } + return _list->thread_at(_index); + } +}; + +// This stack allocated ThreadsListHandle and JavaThreadIterator combo +// is used to walk the ThreadsList in the included ThreadsListHandle +// using the following style: +// +// for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { +// ... +// } +// +class JavaThreadIteratorWithHandle : public StackObj { + ThreadsListHandle _tlh; + uint _index; + +public: + JavaThreadIteratorWithHandle() : _index(0) {} + + uint length() const { + return _tlh.length(); + } + + ThreadsList *list() const { + return _tlh.list(); + } + + JavaThread *next() { + if (_index >= length()) { + return NULL; + } + return _tlh.list()->thread_at(_index++); + } + + void rewind() { + _index = 0; + } +}; + +#endif // SHARE_VM_RUNTIME_THREADSMR_HPP diff --git a/src/hotspot/share/runtime/threadSMR.inline.hpp b/src/hotspot/share/runtime/threadSMR.inline.hpp new file mode 100644 index 00000000000..0203fc6e55f --- /dev/null +++ b/src/hotspot/share/runtime/threadSMR.inline.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, 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_VM_RUNTIME_THREADSMR_INLINE_HPP +#define SHARE_VM_RUNTIME_THREADSMR_INLINE_HPP + +#include "runtime/atomic.hpp" +#include "runtime/prefetch.inline.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" + +// Devirtualize known thread closure types. +template +inline void ThreadsList::threads_do_dispatch(T *cl, JavaThread *const thread) const { + cl->T::do_thread(thread); +} + +template <> +inline void ThreadsList::threads_do_dispatch(ThreadClosure *cl, JavaThread *const thread) const { + cl->do_thread(thread); +} + +template +inline void ThreadsList::threads_do(T *cl) const { + const intx scan_interval = PrefetchScanIntervalInBytes; + JavaThread *const *const end = _threads + _length; + for (JavaThread *const *current_p = _threads; current_p != end; current_p++) { + Prefetch::read((void*)current_p, scan_interval); + JavaThread *const current = *current_p; + threads_do_dispatch(cl, current); + } +} + +inline ThreadsList* ThreadsListSetter::list() { + ThreadsList *ret = _target->get_threads_hazard_ptr(); + assert(ret != NULL, "hazard ptr should be set"); + assert(!Thread::is_hazard_ptr_tagged(ret), "hazard ptr should be validated"); + return ret; +} + +#endif // SHARE_VM_RUNTIME_THREADSMR_INLINE_HPP diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 0466f7ae7db..9fb22233abb 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -830,7 +830,7 @@ typedef PaddedEnd PaddedObjectMonitor; nonstatic_field(nmethod, _osr_link, nmethod*) \ nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \ nonstatic_field(nmethod, _scavenge_root_state, jbyte) \ - nonstatic_field(nmethod, _state, volatile char) \ + nonstatic_field(nmethod, _state, volatile signed char) \ nonstatic_field(nmethod, _exception_offset, int) \ nonstatic_field(nmethod, _orig_pc_offset, int) \ nonstatic_field(nmethod, _stub_offset, int) \ @@ -1350,8 +1350,8 @@ typedef PaddedEnd PaddedObjectMonitor; declare_integer_type(int) \ declare_integer_type(long) \ declare_integer_type(char) \ + declare_integer_type(volatile signed char) \ declare_unsigned_integer_type(unsigned char) \ - declare_unsigned_integer_type(volatile char) \ declare_unsigned_integer_type(u_char) \ declare_unsigned_integer_type(unsigned int) \ declare_unsigned_integer_type(uint) \ @@ -1534,6 +1534,7 @@ typedef PaddedEnd PaddedObjectMonitor; declare_toplevel_type(PerfDataPrologue*) \ declare_toplevel_type(PerfDataEntry) \ declare_toplevel_type(PerfMemory) \ + declare_type(PerfData, CHeapObj) \ \ /*********************************/ \ /* SymbolTable, SystemDictionary */ \ @@ -1958,6 +1959,7 @@ typedef PaddedEnd PaddedObjectMonitor; declare_c2_type(NegFNode, NegNode) \ declare_c2_type(NegDNode, NegNode) \ declare_c2_type(AtanDNode, Node) \ + declare_c2_type(SqrtFNode, Node) \ declare_c2_type(SqrtDNode, Node) \ declare_c2_type(ReverseBytesINode, Node) \ declare_c2_type(ReverseBytesLNode, Node) \ @@ -2480,6 +2482,12 @@ typedef PaddedEnd PaddedObjectMonitor; declare_constant(InstanceKlass::inner_class_access_flags_offset) \ declare_constant(InstanceKlass::inner_class_next_offset) \ \ + /*****************************************************/ \ + /* InstanceKlass EnclosingMethodAttributeOffset enum */ \ + /*****************************************************/ \ + \ + declare_constant(InstanceKlass::enclosing_method_attribute_size) \ + \ /*********************************/ \ /* InstanceKlass ClassState enum */ \ /*********************************/ \ @@ -2635,6 +2643,46 @@ typedef PaddedEnd PaddedObjectMonitor; declare_constant(Deoptimization::_reason_shift) \ declare_constant(Deoptimization::_debug_id_shift) \ \ + /******************************************/ \ + /* BasicType enum (globalDefinitions.hpp) */ \ + /******************************************/ \ + \ + declare_constant(T_BOOLEAN) \ + declare_constant(T_CHAR) \ + declare_constant(T_FLOAT) \ + declare_constant(T_DOUBLE) \ + declare_constant(T_BYTE) \ + declare_constant(T_SHORT) \ + declare_constant(T_INT) \ + declare_constant(T_LONG) \ + declare_constant(T_OBJECT) \ + declare_constant(T_ARRAY) \ + declare_constant(T_VOID) \ + declare_constant(T_ADDRESS) \ + declare_constant(T_NARROWOOP) \ + declare_constant(T_METADATA) \ + declare_constant(T_NARROWKLASS) \ + declare_constant(T_CONFLICT) \ + declare_constant(T_ILLEGAL) \ + \ + /**********************************************/ \ + /* BasicTypeSize enum (globalDefinitions.hpp) */ \ + /**********************************************/ \ + \ + declare_constant(T_BOOLEAN_size) \ + declare_constant(T_CHAR_size) \ + declare_constant(T_FLOAT_size) \ + declare_constant(T_DOUBLE_size) \ + declare_constant(T_BYTE_size) \ + declare_constant(T_SHORT_size) \ + declare_constant(T_INT_size) \ + declare_constant(T_LONG_size) \ + declare_constant(T_OBJECT_size) \ + declare_constant(T_ARRAY_size) \ + declare_constant(T_NARROWOOP_size) \ + declare_constant(T_NARROWKLASS_size) \ + declare_constant(T_VOID_size) \ + \ /*********************/ \ /* Matcher (C2 only) */ \ /*********************/ \ @@ -2733,6 +2781,21 @@ typedef PaddedEnd PaddedObjectMonitor; declare_c2_preprocessor_constant("SAVED_ON_ENTRY_REG_COUNT", SAVED_ON_ENTRY_REG_COUNT) \ declare_c2_preprocessor_constant("C_SAVED_ON_ENTRY_REG_COUNT", C_SAVED_ON_ENTRY_REG_COUNT) \ \ + /************/ \ + /* PerfData */ \ + /************/ \ + \ + /***********************/ \ + /* PerfData Units enum */ \ + /***********************/ \ + \ + declare_constant(PerfData::U_None) \ + declare_constant(PerfData::U_Bytes) \ + declare_constant(PerfData::U_Ticks) \ + declare_constant(PerfData::U_Events) \ + declare_constant(PerfData::U_String) \ + declare_constant(PerfData::U_Hertz) \ + \ /****************/ \ /* JVMCI */ \ /****************/ \ diff --git a/src/hotspot/share/runtime/vm_operations.cpp b/src/hotspot/share/runtime/vm_operations.cpp index e9ad8af4314..9e5608f6f06 100644 --- a/src/hotspot/share/runtime/vm_operations.cpp +++ b/src/hotspot/share/runtime/vm_operations.cpp @@ -38,6 +38,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/sweeper.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.inline.hpp" #include "runtime/vm_operations.hpp" #include "services/threadService.hpp" #include "trace/tracing.hpp" @@ -96,11 +97,12 @@ void VM_Operation::print_on_error(outputStream* st) const { void VM_ThreadStop::doit() { assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); + ThreadsListHandle tlh; JavaThread* target = java_lang_Thread::thread(target_thread()); // Note that this now allows multiple ThreadDeath exceptions to be // thrown at a thread. - if (target != NULL) { - // the thread has run and is not already in the process of exiting + if (target != NULL && (!EnableThreadSMRExtraValidityChecks || tlh.includes(target))) { + // The target thread has run and has not exited yet. target->send_thread_stop(throwable()); } } @@ -146,9 +148,10 @@ void VM_DeoptimizeFrame::doit() { void VM_DeoptimizeAll::doit() { DeoptimizationMarker dm; + JavaThreadIteratorWithHandle jtiwh; // deoptimize all java threads in the system if (DeoptimizeALot) { - for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) { + for (; JavaThread *thread = jtiwh.next(); ) { if (thread->has_last_Java_frame()) { thread->deoptimize(); } @@ -159,7 +162,7 @@ void VM_DeoptimizeAll::doit() { int tnum = os::random() & 0x3; int fnum = os::random() & 0x3; int tcount = 0; - for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) { + for (; JavaThread *thread = jtiwh.next(); ) { if (thread->has_last_Java_frame()) { if (tcount++ == tnum) { tcount = 0; @@ -259,12 +262,19 @@ bool VM_FindDeadlocks::doit_prologue() { } void VM_FindDeadlocks::doit() { - _deadlocks = ThreadService::find_deadlocks_at_safepoint(_concurrent_locks); + // Update the hazard ptr in the originating thread to the current + // list of threads. This VM operation needs the current list of + // threads for proper deadlock detection and those are the + // JavaThreads we need to be protected when we return info to the + // originating thread. + _setter.set(); + + _deadlocks = ThreadService::find_deadlocks_at_safepoint(_setter.list(), _concurrent_locks); if (_out != NULL) { int num_deadlocks = 0; for (DeadlockCycle* cycle = _deadlocks; cycle != NULL; cycle = cycle->next()) { num_deadlocks++; - cycle->print_on(_out); + cycle->print_on_with(_setter.list(), _out); } if (num_deadlocks == 1) { @@ -331,6 +341,12 @@ void VM_ThreadDump::doit_epilogue() { void VM_ThreadDump::doit() { ResourceMark rm; + // Set the hazard ptr in the originating thread to protect the + // current list of threads. This VM operation needs the current list + // of threads for a proper dump and those are the JavaThreads we need + // to be protected when we return info to the originating thread. + _result->set_t_list(); + ConcurrentLocksDump concurrent_locks(true); if (_with_locked_synchronizers) { concurrent_locks.dump_at_safepoint(); @@ -338,7 +354,9 @@ void VM_ThreadDump::doit() { if (_num_threads == 0) { // Snapshot all live threads - for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { + + for (uint i = 0; i < _result->t_list()->length(); i++) { + JavaThread* jt = _result->t_list()->thread_at(i); if (jt->is_exiting() || jt->is_hidden_from_external_view()) { // skip terminating threads and hidden threads @@ -354,6 +372,7 @@ void VM_ThreadDump::doit() { } else { // Snapshot threads in the given _threads array // A dummy snapshot is created if a thread doesn't exist + for (int i = 0; i < _num_threads; i++) { instanceHandle th = _threads->at(i); if (th() == NULL) { @@ -366,6 +385,12 @@ void VM_ThreadDump::doit() { // Dump thread stack only if the thread is alive and not exiting // and not VM internal thread. JavaThread* jt = java_lang_Thread::thread(th()); + if (jt != NULL && !_result->t_list()->includes(jt)) { + // _threads[i] doesn't refer to a valid JavaThread; this check + // is primarily for JVM_DumpThreads() which doesn't have a good + // way to validate the _threads array. + jt = NULL; + } if (jt == NULL || /* thread not alive */ jt->is_exiting() || jt->is_hidden_from_external_view()) { @@ -384,7 +409,7 @@ void VM_ThreadDump::doit() { } ThreadSnapshot* VM_ThreadDump::snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl) { - ThreadSnapshot* snapshot = new ThreadSnapshot(java_thread); + ThreadSnapshot* snapshot = new ThreadSnapshot(_result->t_list(), java_thread); snapshot->dump_stack_at_safepoint(_max_depth, _with_locked_monitors); snapshot->set_concurrent_locks(tcl); return snapshot; @@ -403,11 +428,12 @@ int VM_Exit::set_vm_exited() { _shutdown_thread = thr_cur; _vm_exited = true; // global flag - for(JavaThread *thr = Threads::first(); thr != NULL; thr = thr->next()) + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { if (thr!=thr_cur && thr->thread_state() == _thread_in_native) { ++num_active; thr->set_terminated(JavaThread::_vm_exited); // per-thread flag } + } return num_active; } @@ -435,11 +461,13 @@ int VM_Exit::wait_for_threads_in_native_to_block() { int max_wait = max_wait_compiler_thread; int attempts = 0; + JavaThreadIteratorWithHandle jtiwh; while (true) { int num_active = 0; int num_active_compiler_thread = 0; - for(JavaThread *thr = Threads::first(); thr != NULL; thr = thr->next()) { + jtiwh.rewind(); + for (; JavaThread *thr = jtiwh.next(); ) { if (thr!=thr_cur && thr->thread_state() == _thread_in_native) { num_active++; if (thr->is_Compiler_thread()) { diff --git a/src/hotspot/share/runtime/vm_operations.hpp b/src/hotspot/share/runtime/vm_operations.hpp index 4bc2fdd7794..3311ee8be25 100644 --- a/src/hotspot/share/runtime/vm_operations.hpp +++ b/src/hotspot/share/runtime/vm_operations.hpp @@ -392,12 +392,14 @@ class VM_PrintMetadata : public VM_Operation { class DeadlockCycle; class VM_FindDeadlocks: public VM_Operation { private: - bool _concurrent_locks; - DeadlockCycle* _deadlocks; - outputStream* _out; + bool _concurrent_locks; + DeadlockCycle* _deadlocks; + outputStream* _out; + ThreadsListSetter _setter; // Helper to set hazard ptr in the originating thread + // which protects the JavaThreads in _deadlocks. public: - VM_FindDeadlocks(bool concurrent_locks) : _concurrent_locks(concurrent_locks), _out(NULL), _deadlocks(NULL) {}; + VM_FindDeadlocks(bool concurrent_locks) : _concurrent_locks(concurrent_locks), _out(NULL), _deadlocks(NULL), _setter() {}; VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _out(st), _deadlocks(NULL) {}; ~VM_FindDeadlocks(); diff --git a/src/hotspot/share/services/diagnosticArgument.cpp b/src/hotspot/share/services/diagnosticArgument.cpp index 691bd797dd1..4456260f29b 100644 --- a/src/hotspot/share/services/diagnosticArgument.cpp +++ b/src/hotspot/share/services/diagnosticArgument.cpp @@ -29,6 +29,29 @@ #include "runtime/thread.hpp" #include "services/diagnosticArgument.hpp" +StringArrayArgument::StringArrayArgument() { + _array = new(ResourceObj::C_HEAP, mtInternal)GrowableArray(32, true); + assert(_array != NULL, "Sanity check"); +} + +StringArrayArgument::~StringArrayArgument() { + for (int i=0; i<_array->length(); i++) { + if(_array->at(i) != NULL) { // Safety check + FREE_C_HEAP_ARRAY(char, _array->at(i)); + } + } + delete _array; +} + +void StringArrayArgument::add(const char* str, size_t len) { + if (str != NULL) { + char* ptr = NEW_C_HEAP_ARRAY(char, len+1, mtInternal); + strncpy(ptr, str, len); + ptr[len] = 0; + _array->append(ptr); + } +} + void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) { /* NOTE:Some argument types doesn't require a value, * for instance boolean arguments: "enableFeatureX". is diff --git a/src/hotspot/share/services/diagnosticArgument.hpp b/src/hotspot/share/services/diagnosticArgument.hpp index d276d3b6294..654650ccd68 100644 --- a/src/hotspot/share/services/diagnosticArgument.hpp +++ b/src/hotspot/share/services/diagnosticArgument.hpp @@ -35,29 +35,14 @@ class StringArrayArgument : public CHeapObj { private: GrowableArray* _array; public: - StringArrayArgument() { - _array = new(ResourceObj::C_HEAP, mtInternal)GrowableArray(32, true); - assert(_array != NULL, "Sanity check"); - } - void add(const char* str, size_t len) { - if (str != NULL) { - char* ptr = NEW_C_HEAP_ARRAY(char, len+1, mtInternal); - strncpy(ptr, str, len); - ptr[len] = 0; - _array->append(ptr); - } - } + StringArrayArgument(); + ~StringArrayArgument(); + + void add(const char* str, size_t len); + GrowableArray* array() { return _array; } - ~StringArrayArgument() { - for (int i=0; i<_array->length(); i++) { - if(_array->at(i) != NULL) { // Safety check - FREE_C_HEAP_ARRAY(char, _array->at(i)); - } - } - delete _array; - } }; class NanoTimeArgument { diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp index e931b2ec334..71dbe24f0b5 100644 --- a/src/hotspot/share/services/heapDumper.cpp +++ b/src/hotspot/share/services/heapDumper.cpp @@ -39,6 +39,8 @@ #include "runtime/jniHandles.hpp" #include "runtime/os.hpp" #include "runtime/reflectionUtils.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vframe.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" @@ -1895,7 +1897,7 @@ void VM_HeapDumper::dump_stack_traces() { _stack_traces = NEW_C_HEAP_ARRAY(ThreadStackTrace*, Threads::number_of_threads(), mtInternal); int frame_serial_num = 0; - for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { oop threadObj = thread->threadObj(); if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) { // dump thread stack trace diff --git a/src/hotspot/share/services/jmm.h b/src/hotspot/share/services/jmm.h deleted file mode 100644 index df232f6feec..00000000000 --- a/src/hotspot/share/services/jmm.h +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2003, 2017, 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. - */ - -#ifndef _JAVA_JMM_H_ -#define _JAVA_JMM_H_ - -/* - * This is a private interface used by JDK for JVM monitoring - * and management. - * - * Bump the version number when either of the following happens: - * - * 1. There is a change in functions in JmmInterface. - * - * 2. There is a change in the contract between VM and Java classes. - */ - -#include "jni.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - JMM_VERSION_1 = 0x20010000, - JMM_VERSION_1_0 = 0x20010000, - JMM_VERSION_1_1 = 0x20010100, // JDK 6 - JMM_VERSION_1_2 = 0x20010200, // JDK 7 - JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA - JMM_VERSION_1_2_2 = 0x20010202, - JMM_VERSION_2 = 0x20020000, // JDK 10 - JMM_VERSION = 0x20020000 -}; - -typedef struct { - unsigned int isLowMemoryDetectionSupported : 1; - unsigned int isCompilationTimeMonitoringSupported : 1; - unsigned int isThreadContentionMonitoringSupported : 1; - unsigned int isCurrentThreadCpuTimeSupported : 1; - unsigned int isOtherThreadCpuTimeSupported : 1; - unsigned int isObjectMonitorUsageSupported : 1; - unsigned int isSynchronizerUsageSupported : 1; - unsigned int isThreadAllocatedMemorySupported : 1; - unsigned int isRemoteDiagnosticCommandsSupported : 1; - unsigned int : 22; -} jmmOptionalSupport; - -typedef enum { - JMM_CLASS_LOADED_COUNT = 1, /* Total number of loaded classes */ - JMM_CLASS_UNLOADED_COUNT = 2, /* Total number of unloaded classes */ - JMM_THREAD_TOTAL_COUNT = 3, /* Total number of threads that have been started */ - JMM_THREAD_LIVE_COUNT = 4, /* Current number of live threads */ - JMM_THREAD_PEAK_COUNT = 5, /* Peak number of live threads */ - JMM_THREAD_DAEMON_COUNT = 6, /* Current number of daemon threads */ - JMM_JVM_INIT_DONE_TIME_MS = 7, /* Time when the JVM finished initialization */ - JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ - JMM_GC_TIME_MS = 9, /* Total accumulated time spent in collection */ - JMM_GC_COUNT = 10, /* Total number of collections */ - JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */ - - JMM_INTERNAL_ATTRIBUTE_INDEX = 100, - JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ - JMM_CLASS_UNLOADED_BYTES = 102, /* Number of bytes unloaded instance classes */ - JMM_TOTAL_CLASSLOAD_TIME_MS = 103, /* Accumulated VM class loader time (TraceClassLoadingTime) */ - JMM_VM_GLOBAL_COUNT = 104, /* Number of VM internal flags */ - JMM_SAFEPOINT_COUNT = 105, /* Total number of safepoints */ - JMM_TOTAL_SAFEPOINTSYNC_TIME_MS = 106, /* Accumulated time spent getting to safepoints */ - JMM_TOTAL_STOPPED_TIME_MS = 107, /* Accumulated time spent at safepoints */ - JMM_TOTAL_APP_TIME_MS = 108, /* Accumulated time spent in Java application */ - JMM_VM_THREAD_COUNT = 109, /* Current number of VM internal threads */ - JMM_CLASS_INIT_TOTAL_COUNT = 110, /* Number of classes for which initializers were run */ - JMM_CLASS_INIT_TOTAL_TIME_MS = 111, /* Accumulated time spent in class initializers */ - JMM_METHOD_DATA_SIZE_BYTES = 112, /* Size of method data in memory */ - JMM_CLASS_VERIFY_TOTAL_TIME_MS = 113, /* Accumulated time spent in class verifier */ - JMM_SHARED_CLASS_LOADED_COUNT = 114, /* Number of shared classes loaded */ - JMM_SHARED_CLASS_UNLOADED_COUNT = 115, /* Number of shared classes unloaded */ - JMM_SHARED_CLASS_LOADED_BYTES = 116, /* Number of bytes loaded shared classes */ - JMM_SHARED_CLASS_UNLOADED_BYTES = 117, /* Number of bytes unloaded shared classes */ - - JMM_OS_ATTRIBUTE_INDEX = 200, - JMM_OS_PROCESS_ID = 201, /* Process id of the JVM */ - JMM_OS_MEM_TOTAL_PHYSICAL_BYTES = 202, /* Physical memory size */ - - JMM_GC_EXT_ATTRIBUTE_INFO_SIZE = 401 /* the size of the GC specific attributes for a given GC memory manager */ -} jmmLongAttribute; - -typedef enum { - JMM_VERBOSE_GC = 21, - JMM_VERBOSE_CLASS = 22, - JMM_THREAD_CONTENTION_MONITORING = 23, - JMM_THREAD_CPU_TIME = 24, - JMM_THREAD_ALLOCATED_MEMORY = 25 -} jmmBoolAttribute; - - -enum { - JMM_THREAD_STATE_FLAG_SUSPENDED = 0x00100000, - JMM_THREAD_STATE_FLAG_NATIVE = 0x00400000 -}; - -#define JMM_THREAD_STATE_FLAG_MASK 0xFFF00000 - -typedef enum { - JMM_STAT_PEAK_THREAD_COUNT = 801, - JMM_STAT_THREAD_CONTENTION_COUNT = 802, - JMM_STAT_THREAD_CONTENTION_TIME = 803, - JMM_STAT_THREAD_CONTENTION_STAT = 804, - JMM_STAT_PEAK_POOL_USAGE = 805, - JMM_STAT_GC_STAT = 806 -} jmmStatisticType; - -typedef enum { - JMM_USAGE_THRESHOLD_HIGH = 901, - JMM_USAGE_THRESHOLD_LOW = 902, - JMM_COLLECTION_USAGE_THRESHOLD_HIGH = 903, - JMM_COLLECTION_USAGE_THRESHOLD_LOW = 904 -} jmmThresholdType; - -/* Should match what is allowed in globals.hpp */ -typedef enum { - JMM_VMGLOBAL_TYPE_UNKNOWN = 0, - JMM_VMGLOBAL_TYPE_JBOOLEAN = 1, - JMM_VMGLOBAL_TYPE_JSTRING = 2, - JMM_VMGLOBAL_TYPE_JLONG = 3, - JMM_VMGLOBAL_TYPE_JDOUBLE = 4 -} jmmVMGlobalType; - -typedef enum { - JMM_VMGLOBAL_ORIGIN_DEFAULT = 1, /* Default value */ - JMM_VMGLOBAL_ORIGIN_COMMAND_LINE = 2, /* Set at command line (or JNI invocation) */ - JMM_VMGLOBAL_ORIGIN_MANAGEMENT = 3, /* Set via management interface */ - JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR = 4, /* Set via environment variables */ - JMM_VMGLOBAL_ORIGIN_CONFIG_FILE = 5, /* Set via config file (such as .hotspotrc) */ - JMM_VMGLOBAL_ORIGIN_ERGONOMIC = 6, /* Set via ergonomic */ - JMM_VMGLOBAL_ORIGIN_ATTACH_ON_DEMAND = 7, /* Set via attach */ - JMM_VMGLOBAL_ORIGIN_OTHER = 99 /* Set via some other mechanism */ -} jmmVMGlobalOrigin; - -typedef struct { - jstring name; - jvalue value; - jmmVMGlobalType type; /* Data type */ - jmmVMGlobalOrigin origin; /* Default or non-default value */ - unsigned int writeable : 1; /* dynamically writeable */ - unsigned int external : 1; /* external supported interface */ - unsigned int reserved : 30; - void *reserved1; - void *reserved2; -} jmmVMGlobal; - -typedef struct { - const char* name; - char type; - const char* description; -} jmmExtAttributeInfo; - -/* Caller has to set the following fields before calling GetLastGCStat - * o usage_before_gc - array of MemoryUsage objects - * o usage_after_gc - array of MemoryUsage objects - * o gc_ext_attribute_values_size - size of gc_ext_atttribute_values array - * o gc_ext_attribtue_values - array of jvalues - */ -typedef struct { - jlong gc_index; /* Index of the collections */ - jlong start_time; /* Start time of the GC */ - jlong end_time; /* End time of the GC */ - jobjectArray usage_before_gc; /* Memory usage array before GC */ - jobjectArray usage_after_gc; /* Memory usage array after GC */ - jint gc_ext_attribute_values_size; /* set by the caller of GetGCStat */ - jvalue* gc_ext_attribute_values; /* Array of jvalue for GC extension attributes */ - jint num_gc_ext_attributes; /* number of GC extension attribute values s are filled */ - /* -1 indicates gc_ext_attribute_values is not big enough */ -} jmmGCStat; - -typedef struct { - const char* name; /* Name of the diagnostic command */ - const char* description; /* Short description */ - const char* impact; /* Impact on the JVM */ - const char* permission_class; /* Class name of the required permission if any */ - const char* permission_name; /* Permission name of the required permission if any */ - const char* permission_action; /* Action name of the required permission if any*/ - int num_arguments; /* Number of supported options or arguments */ - jboolean enabled; /* True if the diagnostic command can be invoked, false otherwise */ -} dcmdInfo; - -typedef struct { - const char* name; /* Option/Argument name*/ - const char* description; /* Short description */ - const char* type; /* Type: STRING, BOOLEAN, etc. */ - const char* default_string; /* Default value in a parsable string */ - jboolean mandatory; /* True if the option/argument is mandatory */ - jboolean option; /* True if it is an option, false if it is an argument */ - /* (see diagnosticFramework.hpp for option/argument definitions) */ - jboolean multiple; /* True if the option can be specified several time */ - int position; /* Expected position for this argument (this field is */ - /* meaningless for options) */ -} dcmdArgInfo; - -typedef struct jmmInterface_1_ { - void* reserved1; - void* reserved2; - - jint (JNICALL *GetVersion) (JNIEnv *env); - - jint (JNICALL *GetOptionalSupport) (JNIEnv *env, - jmmOptionalSupport* support_ptr); - - jint (JNICALL *GetThreadInfo) (JNIEnv *env, - jlongArray ids, - jint maxDepth, - jobjectArray infoArray); - - jobjectArray (JNICALL *GetMemoryPools) (JNIEnv* env, jobject mgr); - - jobjectArray (JNICALL *GetMemoryManagers) (JNIEnv* env, jobject pool); - - jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool); - jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool); - - void (JNICALL *GetThreadAllocatedMemory) - (JNIEnv *env, - jlongArray ids, - jlongArray sizeArray); - - jobject (JNICALL *GetMemoryUsage) (JNIEnv* env, jboolean heap); - - jlong (JNICALL *GetLongAttribute) (JNIEnv *env, jobject obj, jmmLongAttribute att); - jboolean (JNICALL *GetBoolAttribute) (JNIEnv *env, jmmBoolAttribute att); - jboolean (JNICALL *SetBoolAttribute) (JNIEnv *env, jmmBoolAttribute att, jboolean flag); - - jint (JNICALL *GetLongAttributes) (JNIEnv *env, - jobject obj, - jmmLongAttribute* atts, - jint count, - jlong* result); - - jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env); - - // Not used in JDK 6 or JDK 7 - jlong (JNICALL *GetThreadCpuTime) (JNIEnv *env, jlong thread_id); - - jobjectArray (JNICALL *GetVMGlobalNames) (JNIEnv *env); - jint (JNICALL *GetVMGlobals) (JNIEnv *env, - jobjectArray names, - jmmVMGlobal *globals, - jint count); - - jint (JNICALL *GetInternalThreadTimes) (JNIEnv *env, - jobjectArray names, - jlongArray times); - - jboolean (JNICALL *ResetStatistic) (JNIEnv *env, - jvalue obj, - jmmStatisticType type); - - void (JNICALL *SetPoolSensor) (JNIEnv *env, - jobject pool, - jmmThresholdType type, - jobject sensor); - - jlong (JNICALL *SetPoolThreshold) (JNIEnv *env, - jobject pool, - jmmThresholdType type, - jlong threshold); - jobject (JNICALL *GetPoolCollectionUsage) (JNIEnv* env, jobject pool); - - jint (JNICALL *GetGCExtAttributeInfo) (JNIEnv *env, - jobject mgr, - jmmExtAttributeInfo *ext_info, - jint count); - void (JNICALL *GetLastGCStat) (JNIEnv *env, - jobject mgr, - jmmGCStat *gc_stat); - - jlong (JNICALL *GetThreadCpuTimeWithKind) - (JNIEnv *env, - jlong thread_id, - jboolean user_sys_cpu_time); - void (JNICALL *GetThreadCpuTimesWithKind) - (JNIEnv *env, - jlongArray ids, - jlongArray timeArray, - jboolean user_sys_cpu_time); - - jint (JNICALL *DumpHeap0) (JNIEnv *env, - jstring outputfile, - jboolean live); - jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env, - jboolean object_monitors_only); - void (JNICALL *SetVMGlobal) (JNIEnv *env, - jstring flag_name, - jvalue new_value); - void* reserved6; - jobjectArray (JNICALL *DumpThreads) (JNIEnv *env, - jlongArray ids, - jboolean lockedMonitors, - jboolean lockedSynchronizers, - jint maxDepth); - void (JNICALL *SetGCNotificationEnabled) (JNIEnv *env, - jobject mgr, - jboolean enabled); - jobjectArray (JNICALL *GetDiagnosticCommands) (JNIEnv *env); - void (JNICALL *GetDiagnosticCommandInfo) - (JNIEnv *env, - jobjectArray cmds, - dcmdInfo *infoArray); - void (JNICALL *GetDiagnosticCommandArgumentsInfo) - (JNIEnv *env, - jstring commandName, - dcmdArgInfo *infoArray); - jstring (JNICALL *ExecuteDiagnosticCommand) - (JNIEnv *env, - jstring command); - void (JNICALL *SetDiagnosticFrameworkNotificationEnabled) - (JNIEnv *env, - jboolean enabled); -} JmmInterface; - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - -#endif /* !_JAVA_JMM_H_ */ diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index bc50816d83d..8273fec1b2e 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "jmm.h" #include "classfile/systemDictionary.hpp" #include "compiler/compileBroker.hpp" #include "memory/iterator.hpp" @@ -41,12 +42,12 @@ #include "runtime/os.hpp" #include "runtime/serviceThread.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "services/classLoadingService.hpp" #include "services/diagnosticCommand.hpp" #include "services/diagnosticFramework.hpp" #include "services/writeableFlags.hpp" #include "services/heapDumper.hpp" -#include "services/jmm.h" #include "services/lowMemoryDetector.hpp" #include "services/gcNotifier.hpp" #include "services/nmtDCmd.hpp" @@ -1025,11 +1026,15 @@ static void do_thread_dump(ThreadDumpResult* dump_result, // First get an array of threadObj handles. // A JavaThread may terminate before we get the stack trace. GrowableArray* thread_handle_array = new GrowableArray(num_threads); + { - MutexLockerEx ml(Threads_lock); + // Need this ThreadsListHandle for converting Java thread IDs into + // threadObj handles; dump_result->set_t_list() is called in the + // VM op below so we can't use it yet. + ThreadsListHandle tlh; for (int i = 0; i < num_threads; i++) { jlong tid = ids_ah->long_at(i); - JavaThread* jt = Threads::find_java_thread_from_java_tid(tid); + JavaThread* jt = tlh.list()->find_JavaThread_from_java_tid(tid); oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL); instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj); thread_handle_array->append(threadObj_h); @@ -1101,22 +1106,21 @@ JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jo ThreadDumpResult dump_result(num_threads); if (maxDepth == 0) { - // no stack trace dumped - do not need to stop the world - { - MutexLockerEx ml(Threads_lock); - for (int i = 0; i < num_threads; i++) { - jlong tid = ids_ah->long_at(i); - JavaThread* jt = Threads::find_java_thread_from_java_tid(tid); - ThreadSnapshot* ts; - if (jt == NULL) { - // if the thread does not exist or now it is terminated, - // create dummy snapshot - ts = new ThreadSnapshot(); - } else { - ts = new ThreadSnapshot(jt); - } - dump_result.add_thread_snapshot(ts); + // No stack trace to dump so we do not need to stop the world. + // Since we never do the VM op here we must set the threads list. + dump_result.set_t_list(); + for (int i = 0; i < num_threads; i++) { + jlong tid = ids_ah->long_at(i); + JavaThread* jt = dump_result.t_list()->find_JavaThread_from_java_tid(tid); + ThreadSnapshot* ts; + if (jt == NULL) { + // if the thread does not exist or now it is terminated, + // create dummy snapshot + ts = new ThreadSnapshot(); + } else { + ts = new ThreadSnapshot(dump_result.t_list(), jt); } + dump_result.add_thread_snapshot(ts); } } else { // obtain thread dump with the specific list of threads with stack trace @@ -1131,6 +1135,7 @@ JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jo int num_snapshots = dump_result.num_snapshots(); assert(num_snapshots == num_threads, "Must match the number of thread snapshots"); + assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot"); int index = 0; for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) { // For each thread, create an java/lang/management/ThreadInfo object @@ -1196,6 +1201,7 @@ JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboo } int num_snapshots = dump_result.num_snapshots(); + assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot"); // create the result ThreadInfo[] object InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); @@ -1319,10 +1325,10 @@ JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType } // Look for the JavaThread of this given tid - MutexLockerEx ml(Threads_lock); + JavaThreadIteratorWithHandle jtiwh; if (tid == 0) { // reset contention statistics for all threads if tid == 0 - for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) { + for (; JavaThread *java_thread = jtiwh.next(); ) { if (type == JMM_STAT_THREAD_CONTENTION_COUNT) { ThreadService::reset_contention_count_stat(java_thread); } else { @@ -1331,7 +1337,7 @@ JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType } } else { // reset contention statistics for a given thread - JavaThread* java_thread = Threads::find_java_thread_from_java_tid(tid); + JavaThread* java_thread = jtiwh.list()->find_JavaThread_from_java_tid(tid); if (java_thread == NULL) { return false; } @@ -1399,8 +1405,8 @@ JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id)) // current thread return os::current_thread_cpu_time(); } else { - MutexLockerEx ml(Threads_lock); - java_thread = Threads::find_java_thread_from_java_tid(thread_id); + ThreadsListHandle tlh; + java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id); if (java_thread != NULL) { return os::thread_cpu_time((Thread*) java_thread); } @@ -1649,6 +1655,7 @@ ThreadTimesClosure::ThreadTimesClosure(objArrayHandle names, // Called with Threads_lock held // void ThreadTimesClosure::do_thread(Thread* thread) { + assert(Threads_lock->owned_by_self(), "Must hold Threads_lock"); assert(thread != NULL, "thread was NULL"); // exclude externally visible JavaThreads @@ -2109,9 +2116,9 @@ JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids, "the given array of thread IDs"); } - MutexLockerEx ml(Threads_lock); + ThreadsListHandle tlh; for (int i = 0; i < num_threads; i++) { - JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i)); + JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i)); if (java_thread != NULL) { sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes()); } @@ -2138,8 +2145,8 @@ JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboo // current thread return os::current_thread_cpu_time(user_sys_cpu_time != 0); } else { - MutexLockerEx ml(Threads_lock); - java_thread = Threads::find_java_thread_from_java_tid(thread_id); + ThreadsListHandle tlh; + java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id); if (java_thread != NULL) { return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0); } @@ -2180,9 +2187,9 @@ JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids, "the given array of thread IDs"); } - MutexLockerEx ml(Threads_lock); + ThreadsListHandle tlh; for (int i = 0; i < num_threads; i++) { - JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i)); + JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i)); if (java_thread != NULL) { timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread, user_sys_cpu_time != 0)); diff --git a/src/hotspot/share/services/management.hpp b/src/hotspot/share/services/management.hpp index f1168166281..4f475060d67 100644 --- a/src/hotspot/share/services/management.hpp +++ b/src/hotspot/share/services/management.hpp @@ -25,10 +25,10 @@ #ifndef SHARE_VM_SERVICES_MANAGEMENT_HPP #define SHARE_VM_SERVICES_MANAGEMENT_HPP +#include "jmm.h" #include "memory/allocation.hpp" #include "runtime/handles.hpp" #include "runtime/timer.hpp" -#include "services/jmm.h" class OopClosure; class ThreadSnapshot; diff --git a/src/hotspot/share/services/memoryManager.cpp b/src/hotspot/share/services/memoryManager.cpp index 8c6fc6d6f1a..5bc16bfd837 100644 --- a/src/hotspot/share/services/memoryManager.cpp +++ b/src/hotspot/share/services/memoryManager.cpp @@ -37,7 +37,7 @@ #include "services/gcNotifier.hpp" #include "utilities/dtrace.hpp" -MemoryManager::MemoryManager() { +MemoryManager::MemoryManager(const char* name) : _name(name) { _num_pools = 0; (void)const_cast(_memory_mgr_obj = instanceOop(NULL)); } @@ -52,43 +52,11 @@ void MemoryManager::add_pool(MemoryPool* pool) { } MemoryManager* MemoryManager::get_code_cache_memory_manager() { - return (MemoryManager*) new CodeCacheMemoryManager(); + return new MemoryManager("CodeCacheManager"); } MemoryManager* MemoryManager::get_metaspace_memory_manager() { - return (MemoryManager*) new MetaspaceMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_copy_memory_manager() { - return (GCMemoryManager*) new CopyMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_msc_memory_manager() { - return (GCMemoryManager*) new MSCMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_parnew_memory_manager() { - return (GCMemoryManager*) new ParNewMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_cms_memory_manager() { - return (GCMemoryManager*) new CMSMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_psScavenge_memory_manager() { - return (GCMemoryManager*) new PSScavengeMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_psMarkSweep_memory_manager() { - return (GCMemoryManager*) new PSMarkSweepMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_g1YoungGen_memory_manager() { - return (GCMemoryManager*) new G1YoungGenMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_g1OldGen_memory_manager() { - return (GCMemoryManager*) new G1OldGenMemoryManager(); + return new MemoryManager("Metaspace Manager"); } instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { @@ -203,7 +171,8 @@ void GCStatInfo::clear() { } -GCMemoryManager::GCMemoryManager() : MemoryManager() { +GCMemoryManager::GCMemoryManager(const char* name, const char* gc_end_message) : + MemoryManager(name), _gc_end_message(gc_end_message) { _num_collections = 0; _last_gc_stat = NULL; _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true, @@ -308,9 +277,7 @@ void GCMemoryManager::gc_end(bool recordPostGCUsage, } if (is_notification_enabled()) { - bool isMajorGC = this == MemoryService::get_major_gc_manager(); - GCNotifier::pushNotification(this, isMajorGC ? "end of major GC" : "end of minor GC", - GCCause::to_string(cause)); + GCNotifier::pushNotification(this, _gc_end_message, GCCause::to_string(cause)); } } } diff --git a/src/hotspot/share/services/memoryManager.hpp b/src/hotspot/share/services/memoryManager.hpp index f2a7d4c3420..7d8ef854813 100644 --- a/src/hotspot/share/services/memoryManager.hpp +++ b/src/hotspot/share/services/memoryManager.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,10 @@ #ifndef SHARE_VM_SERVICES_MEMORYMANAGER_HPP #define SHARE_VM_SERVICES_MEMORYMANAGER_HPP +#include "gc/shared/gcCause.hpp" #include "memory/allocation.hpp" +#include "oops/oopsHierarchy.hpp" +#include "runtime/handles.hpp" #include "runtime/timer.hpp" #include "services/memoryUsage.hpp" @@ -49,11 +52,13 @@ private: MemoryPool* _pools[max_num_pools]; int _num_pools; + const char* _name; + protected: volatile instanceOop _memory_mgr_obj; public: - MemoryManager(); + MemoryManager(const char* name); int num_memory_pools() const { return _num_pools; } MemoryPool* get_memory_pool(int index) { @@ -67,7 +72,8 @@ public: virtual instanceOop get_memory_manager_instance(TRAPS); virtual bool is_gc_memory_manager() { return false; } - virtual const char* name() = 0; + + const char* name() const { return _name; } // GC support void oops_do(OopClosure* f); @@ -75,29 +81,6 @@ public: // Static factory methods to get a memory manager of a specific type static MemoryManager* get_code_cache_memory_manager(); static MemoryManager* get_metaspace_memory_manager(); - static GCMemoryManager* get_copy_memory_manager(); - static GCMemoryManager* get_msc_memory_manager(); - static GCMemoryManager* get_parnew_memory_manager(); - static GCMemoryManager* get_cms_memory_manager(); - static GCMemoryManager* get_psScavenge_memory_manager(); - static GCMemoryManager* get_psMarkSweep_memory_manager(); - static GCMemoryManager* get_g1YoungGen_memory_manager(); - static GCMemoryManager* get_g1OldGen_memory_manager(); -}; - -class CodeCacheMemoryManager : public MemoryManager { -private: -public: - CodeCacheMemoryManager() : MemoryManager() {} - - const char* name() { return "CodeCacheManager"; } -}; - -class MetaspaceMemoryManager : public MemoryManager { -public: - MetaspaceMemoryManager() : MemoryManager() {} - - const char* name() { return "Metaspace Manager"; } }; class GCStatInfo : public ResourceObj { @@ -159,8 +142,9 @@ private: GCStatInfo* _current_gc_stat; int _num_gc_threads; volatile bool _notification_enabled; + const char* _gc_end_message; public: - GCMemoryManager(); + GCMemoryManager(const char* name, const char* gc_end_message); ~GCMemoryManager(); void initialize_gc_stat_info(); @@ -186,71 +170,4 @@ public: bool is_notification_enabled() { return _notification_enabled; } }; -// These subclasses of GCMemoryManager are defined to include -// GC-specific information. -// TODO: Add GC-specific information -class CopyMemoryManager : public GCMemoryManager { -private: -public: - CopyMemoryManager() : GCMemoryManager() {} - - const char* name() { return "Copy"; } -}; - -class MSCMemoryManager : public GCMemoryManager { -private: -public: - MSCMemoryManager() : GCMemoryManager() {} - - const char* name() { return "MarkSweepCompact"; } -}; - -class ParNewMemoryManager : public GCMemoryManager { -private: -public: - ParNewMemoryManager() : GCMemoryManager() {} - - const char* name() { return "ParNew"; } -}; - -class CMSMemoryManager : public GCMemoryManager { -private: -public: - CMSMemoryManager() : GCMemoryManager() {} - - const char* name() { return "ConcurrentMarkSweep";} -}; - -class PSScavengeMemoryManager : public GCMemoryManager { -private: -public: - PSScavengeMemoryManager() : GCMemoryManager() {} - - const char* name() { return "PS Scavenge"; } -}; - -class PSMarkSweepMemoryManager : public GCMemoryManager { -private: -public: - PSMarkSweepMemoryManager() : GCMemoryManager() {} - - const char* name() { return "PS MarkSweep"; } -}; - -class G1YoungGenMemoryManager : public GCMemoryManager { -private: -public: - G1YoungGenMemoryManager() : GCMemoryManager() {} - - const char* name() { return "G1 Young Generation"; } -}; - -class G1OldGenMemoryManager : public GCMemoryManager { -private: -public: - G1OldGenMemoryManager() : GCMemoryManager() {} - - const char* name() { return "G1 Old Generation"; } -}; - #endif // SHARE_VM_SERVICES_MEMORYMANAGER_HPP diff --git a/src/hotspot/share/services/memoryPool.cpp b/src/hotspot/share/services/memoryPool.cpp index cec78ae67a4..8248b472225 100644 --- a/src/hotspot/share/services/memoryPool.cpp +++ b/src/hotspot/share/services/memoryPool.cpp @@ -25,8 +25,6 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" -#include "gc/serial/defNewGeneration.hpp" -#include "gc/shared/space.hpp" #include "memory/metaspace.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" @@ -38,9 +36,6 @@ #include "services/memoryPool.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/cms/compactibleFreeListSpace.hpp" -#endif MemoryPool::MemoryPool(const char* name, PoolType type, @@ -182,95 +177,6 @@ void MemoryPool::oops_do(OopClosure* f) { } } -ContiguousSpacePool::ContiguousSpacePool(ContiguousSpace* space, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, space->capacity(), max_size, - support_usage_threshold), _space(space) { -} - -size_t ContiguousSpacePool::used_in_bytes() { - return space()->used(); -} - -MemoryUsage ContiguousSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = _space->capacity(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - -SurvivorContiguousSpacePool::SurvivorContiguousSpacePool(DefNewGeneration* young_gen, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, young_gen->from()->capacity(), max_size, - support_usage_threshold), _young_gen(young_gen) { -} - -size_t SurvivorContiguousSpacePool::used_in_bytes() { - return _young_gen->from()->used(); -} - -size_t SurvivorContiguousSpacePool::committed_in_bytes() { - return _young_gen->from()->capacity(); -} - -MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = committed_in_bytes(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - -#if INCLUDE_ALL_GCS -CompactibleFreeListSpacePool::CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, space->capacity(), max_size, - support_usage_threshold), _space(space) { -} - -size_t CompactibleFreeListSpacePool::used_in_bytes() { - return _space->used(); -} - -MemoryUsage CompactibleFreeListSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = _space->capacity(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} -#endif // INCLUDE_ALL_GCS - -GenerationPool::GenerationPool(Generation* gen, - const char* name, - PoolType type, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, gen->capacity(), gen->max_capacity(), - support_usage_threshold), _gen(gen) { -} - -size_t GenerationPool::used_in_bytes() { - return _gen->used(); -} - -MemoryUsage GenerationPool::get_memory_usage() { - size_t used = used_in_bytes(); - size_t committed = _gen->capacity(); - size_t maxSize = (available_for_allocation() ? max_size() : 0); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - CodeHeapPool::CodeHeapPool(CodeHeap* codeHeap, const char* name, bool support_usage_threshold) : MemoryPool(name, NonHeap, codeHeap->capacity(), codeHeap->max_capacity(), support_usage_threshold, false), _codeHeap(codeHeap) { diff --git a/src/hotspot/share/services/memoryPool.hpp b/src/hotspot/share/services/memoryPool.hpp index 0144f61786c..b1c21580b43 100644 --- a/src/hotspot/share/services/memoryPool.hpp +++ b/src/hotspot/share/services/memoryPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -37,12 +37,8 @@ // both heap and non-heap memory. // Forward declaration -class CompactibleFreeListSpace; -class ContiguousSpace; class MemoryManager; class SensorInfo; -class Generation; -class DefNewGeneration; class ThresholdSupport; class MemoryPool : public CHeapObj { @@ -144,67 +140,11 @@ class MemoryPool : public CHeapObj { class CollectedMemoryPool : public MemoryPool { public: - CollectedMemoryPool(const char* name, PoolType type, size_t init_size, size_t max_size, bool support_usage_threshold) : - MemoryPool(name, type, init_size, max_size, support_usage_threshold, true) {}; + CollectedMemoryPool(const char* name, size_t init_size, size_t max_size, bool support_usage_threshold) : + MemoryPool(name, MemoryPool::Heap, init_size, max_size, support_usage_threshold, true) {}; bool is_collected_pool() { return true; } }; -class ContiguousSpacePool : public CollectedMemoryPool { -private: - ContiguousSpace* _space; - -public: - ContiguousSpacePool(ContiguousSpace* space, const char* name, PoolType type, size_t max_size, bool support_usage_threshold); - - ContiguousSpace* space() { return _space; } - MemoryUsage get_memory_usage(); - size_t used_in_bytes(); -}; - -class SurvivorContiguousSpacePool : public CollectedMemoryPool { -private: - DefNewGeneration* _young_gen; - -public: - SurvivorContiguousSpacePool(DefNewGeneration* young_gen, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - - size_t used_in_bytes(); - size_t committed_in_bytes(); -}; - -#if INCLUDE_ALL_GCS -class CompactibleFreeListSpacePool : public CollectedMemoryPool { -private: - CompactibleFreeListSpace* _space; -public: - CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - size_t used_in_bytes(); -}; -#endif // INCLUDE_ALL_GCS - - -class GenerationPool : public CollectedMemoryPool { -private: - Generation* _gen; -public: - GenerationPool(Generation* gen, const char* name, PoolType type, bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - size_t used_in_bytes(); -}; - class CodeHeapPool: public MemoryPool { private: CodeHeap* _codeHeap; diff --git a/src/hotspot/share/services/memoryService.cpp b/src/hotspot/share/services/memoryService.cpp index d579cd91738..e96e2a0d151 100644 --- a/src/hotspot/share/services/memoryService.cpp +++ b/src/hotspot/share/services/memoryService.cpp @@ -25,13 +25,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" -#include "gc/parallel/mutableSpace.hpp" -#include "gc/serial/defNewGeneration.hpp" -#include "gc/serial/tenuredGeneration.hpp" -#include "gc/shared/collectorPolicy.hpp" -#include "gc/shared/genCollectedHeap.hpp" -#include "gc/shared/generation.hpp" -#include "gc/shared/generationSpec.hpp" +#include "gc/shared/collectedHeap.hpp" #include "logging/logConfiguration.hpp" #include "memory/heap.hpp" #include "memory/memRegion.hpp" @@ -46,24 +40,12 @@ #include "services/memoryService.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/cms/concurrentMarkSweepGeneration.hpp" -#include "gc/cms/parNewGeneration.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/parallel/parallelScavengeHeap.hpp" -#include "gc/parallel/psOldGen.hpp" -#include "gc/parallel/psYoungGen.hpp" -#include "services/g1MemoryPool.hpp" -#include "services/psMemoryPool.hpp" -#endif // INCLUDE_ALL_GCS GrowableArray* MemoryService::_pools_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_pools_list_size, true); GrowableArray* MemoryService::_managers_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_managers_list_size, true); -GCMemoryManager* MemoryService::_minor_gc_manager = NULL; -GCMemoryManager* MemoryService::_major_gc_manager = NULL; MemoryManager* MemoryService::_code_cache_manager = NULL; GrowableArray* MemoryService::_code_heap_pools = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_code_heap_pools_size, true); @@ -84,311 +66,28 @@ void GcThreadCountClosure::do_thread(Thread* thread) { } void MemoryService::set_universe_heap(CollectedHeap* heap) { - CollectedHeap::Name kind = heap->kind(); - switch (kind) { - case CollectedHeap::SerialHeap : - case CollectedHeap::CMSHeap : { - add_gen_collected_heap_info(GenCollectedHeap::heap()); - break; - } -#if INCLUDE_ALL_GCS - case CollectedHeap::ParallelScavengeHeap : { - add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap()); - break; - } - case CollectedHeap::G1CollectedHeap : { - add_g1_heap_info(G1CollectedHeap::heap()); - break; - } -#endif // INCLUDE_ALL_GCS - default: { - guarantee(false, "Unrecognized kind of heap"); - } - } + ResourceMark rm; // For internal allocations in GrowableArray. + + GrowableArray gc_mem_pools = heap->memory_pools(); + _pools_list->appendAll(&gc_mem_pools); // set the GC thread count GcThreadCountClosure gctcc; heap->gc_threads_do(&gctcc); int count = gctcc.count(); - if (count > 0) { - _minor_gc_manager->set_num_gc_threads(count); - _major_gc_manager->set_num_gc_threads(count); - } - // All memory pools and memory managers are initialized. - // - _minor_gc_manager->initialize_gc_stat_info(); - _major_gc_manager->initialize_gc_stat_info(); -} + GrowableArray gc_memory_managers = heap->memory_managers(); + for (int i = 0; i < gc_memory_managers.length(); i++) { + GCMemoryManager* gc_manager = gc_memory_managers.at(i); -// Add memory pools for GenCollectedHeap -// This function currently only supports two generations collected heap. -// The collector for GenCollectedHeap will have two memory managers. -void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) { - CollectorPolicy* policy = heap->collector_policy(); - - assert(policy->is_generation_policy(), "Only support two generations"); - GenCollectorPolicy* gen_policy = policy->as_generation_policy(); - if (gen_policy != NULL) { - Generation::Name kind = gen_policy->young_gen_spec()->name(); - switch (kind) { - case Generation::DefNew: - _minor_gc_manager = MemoryManager::get_copy_memory_manager(); - break; -#if INCLUDE_ALL_GCS - case Generation::ParNew: - _minor_gc_manager = MemoryManager::get_parnew_memory_manager(); - break; -#endif // INCLUDE_ALL_GCS - default: - guarantee(false, "Unrecognized generation spec"); - break; - } - if (policy->is_mark_sweep_policy()) { - _major_gc_manager = MemoryManager::get_msc_memory_manager(); -#if INCLUDE_ALL_GCS - } else if (policy->is_concurrent_mark_sweep_policy()) { - _major_gc_manager = MemoryManager::get_cms_memory_manager(); -#endif // INCLUDE_ALL_GCS - } else { - guarantee(false, "Unknown two-gen policy"); - } - } else { - guarantee(false, "Non two-gen policy"); - } - _managers_list->append(_minor_gc_manager); - _managers_list->append(_major_gc_manager); - - add_generation_memory_pool(heap->young_gen(), _major_gc_manager, _minor_gc_manager); - add_generation_memory_pool(heap->old_gen(), _major_gc_manager); -} - -#if INCLUDE_ALL_GCS -// Add memory pools for ParallelScavengeHeap -// This function currently only supports two generations collected heap. -// The collector for ParallelScavengeHeap will have two memory managers. -void MemoryService::add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap) { - // Two managers to keep statistics about _minor_gc_manager and _major_gc_manager GC. - _minor_gc_manager = MemoryManager::get_psScavenge_memory_manager(); - _major_gc_manager = MemoryManager::get_psMarkSweep_memory_manager(); - _managers_list->append(_minor_gc_manager); - _managers_list->append(_major_gc_manager); - - add_psYoung_memory_pool(heap->young_gen(), _major_gc_manager, _minor_gc_manager); - add_psOld_memory_pool(heap->old_gen(), _major_gc_manager); -} - -void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) { - assert(UseG1GC, "sanity"); - - _minor_gc_manager = MemoryManager::get_g1YoungGen_memory_manager(); - _major_gc_manager = MemoryManager::get_g1OldGen_memory_manager(); - _managers_list->append(_minor_gc_manager); - _managers_list->append(_major_gc_manager); - - add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager); - add_g1OldGen_memory_pool(g1h, _major_gc_manager); -} -#endif // INCLUDE_ALL_GCS - -MemoryPool* MemoryService::add_gen(Generation* gen, - const char* name, - bool is_heap, - bool support_usage_threshold) { - - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - GenerationPool* pool = new GenerationPool(gen, name, type, support_usage_threshold); - _pools_list->append(pool); - return (MemoryPool*) pool; -} - -MemoryPool* MemoryService::add_space(ContiguousSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold) { - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - ContiguousSpacePool* pool = new ContiguousSpacePool(space, name, type, max_size, support_usage_threshold); - - _pools_list->append(pool); - return (MemoryPool*) pool; -} - -MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* young_gen, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold) { - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - SurvivorContiguousSpacePool* pool = new SurvivorContiguousSpacePool(young_gen, name, type, max_size, support_usage_threshold); - - _pools_list->append(pool); - return (MemoryPool*) pool; -} - -#if INCLUDE_ALL_GCS -MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold) { - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - CompactibleFreeListSpacePool* pool = new CompactibleFreeListSpacePool(space, name, type, max_size, support_usage_threshold); - _pools_list->append(pool); - return (MemoryPool*) pool; -} -#endif // INCLUDE_ALL_GCS - -// Add memory pool(s) for one generation -void MemoryService::add_generation_memory_pool(Generation* gen, - MemoryManager* major_mgr, - MemoryManager* minor_mgr) { - guarantee(gen != NULL, "No generation for memory pool"); - Generation::Name kind = gen->kind(); - int index = _pools_list->length(); - - switch (kind) { - case Generation::DefNew: { - assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); - DefNewGeneration* young_gen = (DefNewGeneration*) gen; - // Add a memory pool for each space and young gen doesn't - // support low memory detection as it is expected to get filled up. - MemoryPool* eden = add_space(young_gen->eden(), - "Eden Space", - true, /* is_heap */ - young_gen->max_eden_size(), - false /* support_usage_threshold */); - MemoryPool* survivor = add_survivor_spaces(young_gen, - "Survivor Space", - true, /* is_heap */ - young_gen->max_survivor_size(), - false /* support_usage_threshold */); - break; - } - -#if INCLUDE_ALL_GCS - case Generation::ParNew: - { - assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); - // Add a memory pool for each space and young gen doesn't - // support low memory detection as it is expected to get filled up. - ParNewGeneration* parnew_gen = (ParNewGeneration*) gen; - MemoryPool* eden = add_space(parnew_gen->eden(), - "Par Eden Space", - true /* is_heap */, - parnew_gen->max_eden_size(), - false /* support_usage_threshold */); - MemoryPool* survivor = add_survivor_spaces(parnew_gen, - "Par Survivor Space", - true, /* is_heap */ - parnew_gen->max_survivor_size(), - false /* support_usage_threshold */); - - break; - } -#endif // INCLUDE_ALL_GCS - - case Generation::MarkSweepCompact: { - assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager"); - add_gen(gen, - "Tenured Gen", - true, /* is_heap */ - true /* support_usage_threshold */); - break; - } - -#if INCLUDE_ALL_GCS - case Generation::ConcurrentMarkSweep: - { - assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager"); - ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*) gen; - MemoryPool* pool = add_cms_space(cms->cmsSpace(), - "CMS Old Gen", - true, /* is_heap */ - cms->reserved().byte_size(), - true /* support_usage_threshold */); - break; - } -#endif // INCLUDE_ALL_GCS - - default: - assert(false, "should not reach here"); - // no memory pool added for others - break; - } - - assert(major_mgr != NULL, "Should have at least one manager"); - // Link managers and the memory pools together - for (int i = index; i < _pools_list->length(); i++) { - MemoryPool* pool = _pools_list->at(i); - major_mgr->add_pool(pool); - if (minor_mgr != NULL) { - minor_mgr->add_pool(pool); + if (count > 0) { + gc_manager->set_num_gc_threads(count); } + gc_manager->initialize_gc_stat_info(); + _managers_list->append(gc_manager); } } - -#if INCLUDE_ALL_GCS -void MemoryService::add_psYoung_memory_pool(PSYoungGen* young_gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) { - assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); - - // Add a memory pool for each space and young gen doesn't - // support low memory detection as it is expected to get filled up. - EdenMutableSpacePool* eden = new EdenMutableSpacePool(young_gen, - young_gen->eden_space(), - "PS Eden Space", - MemoryPool::Heap, - false /* support_usage_threshold */); - - SurvivorMutableSpacePool* survivor = new SurvivorMutableSpacePool(young_gen, - "PS Survivor Space", - MemoryPool::Heap, - false /* support_usage_threshold */); - - major_mgr->add_pool(eden); - major_mgr->add_pool(survivor); - minor_mgr->add_pool(eden); - minor_mgr->add_pool(survivor); - _pools_list->append(eden); - _pools_list->append(survivor); -} - -void MemoryService::add_psOld_memory_pool(PSOldGen* old_gen, MemoryManager* mgr) { - PSGenerationPool* old_gen_pool = new PSGenerationPool(old_gen, - "PS Old Gen", - MemoryPool::Heap, - true /* support_usage_threshold */); - mgr->add_pool(old_gen_pool); - _pools_list->append(old_gen_pool); -} - -void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* major_mgr, - MemoryManager* minor_mgr) { - assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers"); - - G1EdenPool* eden = new G1EdenPool(g1h); - G1SurvivorPool* survivor = new G1SurvivorPool(g1h); - - major_mgr->add_pool(eden); - major_mgr->add_pool(survivor); - minor_mgr->add_pool(eden); - minor_mgr->add_pool(survivor); - _pools_list->append(eden); - _pools_list->append(survivor); -} - -void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* mgr) { - assert(mgr != NULL, "should have one manager"); - - G1OldGenPool* old_gen = new G1OldGenPool(g1h); - mgr->add_pool(old_gen); - _pools_list->append(old_gen); -} -#endif // INCLUDE_ALL_GCS - void MemoryService::add_code_heap_memory_pool(CodeHeap* heap, const char* name) { // Create new memory pool for this heap MemoryPool* code_heap_pool = new CodeHeapPool(heap, name, true /* support_usage_threshold */); @@ -463,18 +162,11 @@ void MemoryService::track_memory_pool_usage(MemoryPool* pool) { } } -void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime, +void MemoryService::gc_begin(GCMemoryManager* manager, bool recordGCBeginTime, bool recordAccumulatedGCTime, bool recordPreGCUsage, bool recordPeakUsage) { - GCMemoryManager* mgr; - if (fullGC) { - mgr = _major_gc_manager; - } else { - mgr = _minor_gc_manager; - } - assert(mgr->is_gc_memory_manager(), "Sanity check"); - mgr->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime); + manager->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime); // Track the peak memory usage when GC begins if (recordPeakUsage) { @@ -485,22 +177,13 @@ void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime, } } -void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage, +void MemoryService::gc_end(GCMemoryManager* manager, bool recordPostGCUsage, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection, GCCause::Cause cause) { - - GCMemoryManager* mgr; - if (fullGC) { - mgr = (GCMemoryManager*) _major_gc_manager; - } else { - mgr = (GCMemoryManager*) _minor_gc_manager; - } - assert(mgr->is_gc_memory_manager(), "Sanity check"); - // register the GC end statistics and memory usage - mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, - countCollection, cause); + manager->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, + countCollection, cause); } void MemoryService::oops_do(OopClosure* f) { @@ -551,36 +234,7 @@ Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { return obj; } -// GC manager type depends on the type of Generation. Depending on the space -// availability and vm options the gc uses major gc manager or minor gc -// manager or both. The type of gc manager depends on the generation kind. -// For DefNew and ParNew generation doing scavenge gc uses minor gc manager (so -// _fullGC is set to false ) and for other generation kinds doing -// mark-sweep-compact uses major gc manager (so _fullGC is set to true). -TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) { - switch (kind) { - case Generation::DefNew: -#if INCLUDE_ALL_GCS - case Generation::ParNew: -#endif // INCLUDE_ALL_GCS - _fullGC = false; - break; - case Generation::MarkSweepCompact: -#if INCLUDE_ALL_GCS - case Generation::ConcurrentMarkSweep: -#endif // INCLUDE_ALL_GCS - _fullGC = true; - break; - default: - _fullGC = false; - assert(false, "Unrecognized gc generation kind."); - } - // this has to be called in a stop the world pause and represent - // an entire gc pause, start to finish: - initialize(_fullGC, cause, true, true, true, true, true, true, true); -} - -TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC, +TraceMemoryManagerStats::TraceMemoryManagerStats(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime, bool recordPreGCUsage, @@ -589,14 +243,14 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection) { - initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, + initialize(gc_memory_manager, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, countCollection); } // for a subclass to create then initialize an instance before invoking // the MemoryService -void TraceMemoryManagerStats::initialize(bool fullGC, +void TraceMemoryManagerStats::initialize(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime, bool recordPreGCUsage, @@ -605,7 +259,7 @@ void TraceMemoryManagerStats::initialize(bool fullGC, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection) { - _fullGC = fullGC; + _gc_memory_manager = gc_memory_manager; _recordGCBeginTime = recordGCBeginTime; _recordPreGCUsage = recordPreGCUsage; _recordPeakUsage = recordPeakUsage; @@ -615,11 +269,11 @@ void TraceMemoryManagerStats::initialize(bool fullGC, _countCollection = countCollection; _cause = cause; - MemoryService::gc_begin(_fullGC, _recordGCBeginTime, _recordAccumulatedGCTime, + MemoryService::gc_begin(_gc_memory_manager, _recordGCBeginTime, _recordAccumulatedGCTime, _recordPreGCUsage, _recordPeakUsage); } TraceMemoryManagerStats::~TraceMemoryManagerStats() { - MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime, + MemoryService::gc_end(_gc_memory_manager, _recordPostGCUsage, _recordAccumulatedGCTime, _recordGCEndTime, _countCollection, _cause); } diff --git a/src/hotspot/share/services/memoryService.hpp b/src/hotspot/share/services/memoryService.hpp index 86a6a95fa90..4ebc0813f23 100644 --- a/src/hotspot/share/services/memoryService.hpp +++ b/src/hotspot/share/services/memoryService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ #define SHARE_VM_SERVICES_MEMORYSERVICE_HPP #include "gc/shared/gcCause.hpp" -#include "gc/shared/generation.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "runtime/handles.hpp" @@ -37,16 +36,7 @@ class MemoryPool; class MemoryManager; class GCMemoryManager; class CollectedHeap; -class Generation; -class DefNewGeneration; -class PSYoungGen; -class PSOldGen; class CodeHeap; -class ContiguousSpace; -class CompactibleFreeListSpace; -class GenCollectedHeap; -class ParallelScavengeHeap; -class G1CollectedHeap; // VM Monitoring and Management Support @@ -61,10 +51,6 @@ private: static GrowableArray* _pools_list; static GrowableArray* _managers_list; - // memory managers for minor and major GC statistics - static GCMemoryManager* _major_gc_manager; - static GCMemoryManager* _minor_gc_manager; - // memory manager and code heap pools for the CodeCache static MemoryManager* _code_cache_manager; static GrowableArray* _code_heap_pools; @@ -72,51 +58,6 @@ private: static MemoryPool* _metaspace_pool; static MemoryPool* _compressed_class_pool; - static void add_generation_memory_pool(Generation* gen, - MemoryManager* major_mgr, - MemoryManager* minor_mgr); - static void add_generation_memory_pool(Generation* gen, - MemoryManager* major_mgr) { - add_generation_memory_pool(gen, major_mgr, NULL); - } - - - static void add_psYoung_memory_pool(PSYoungGen* young_gen, - MemoryManager* major_mgr, - MemoryManager* minor_mgr); - static void add_psOld_memory_pool(PSOldGen* old_gen, - MemoryManager* mgr); - - static void add_g1YoungGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* major_mgr, - MemoryManager* minor_mgr); - static void add_g1OldGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* mgr); - - static MemoryPool* add_space(ContiguousSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold); - static MemoryPool* add_survivor_spaces(DefNewGeneration* young_gen, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold); - static MemoryPool* add_gen(Generation* gen, - const char* name, - bool is_heap, - bool support_usage_threshold); - static MemoryPool* add_cms_space(CompactibleFreeListSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold); - - static void add_gen_collected_heap_info(GenCollectedHeap* heap); - static void add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap); - static void add_g1_heap_info(G1CollectedHeap* g1h); - public: static void set_universe_heap(CollectedHeap* heap); static void add_code_heap_memory_pool(CodeHeap* heap, const char* name); @@ -155,10 +96,10 @@ public: } static void track_memory_pool_usage(MemoryPool* pool); - static void gc_begin(bool fullGC, bool recordGCBeginTime, + static void gc_begin(GCMemoryManager* manager, bool recordGCBeginTime, bool recordAccumulatedGCTime, bool recordPreGCUsage, bool recordPeakUsage); - static void gc_end(bool fullGC, bool recordPostGCUsage, + static void gc_end(GCMemoryManager* manager, bool recordPostGCUsage, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection, GCCause::Cause cause); @@ -170,19 +111,11 @@ public: // Create an instance of java/lang/management/MemoryUsage static Handle create_MemoryUsage_obj(MemoryUsage usage, TRAPS); - - static const GCMemoryManager* get_minor_gc_manager() { - return _minor_gc_manager; - } - - static const GCMemoryManager* get_major_gc_manager() { - return _major_gc_manager; - } }; class TraceMemoryManagerStats : public StackObj { private: - bool _fullGC; + GCMemoryManager* _gc_memory_manager; bool _recordGCBeginTime; bool _recordPreGCUsage; bool _recordPeakUsage; @@ -193,7 +126,7 @@ private: GCCause::Cause _cause; public: TraceMemoryManagerStats() {} - TraceMemoryManagerStats(bool fullGC, + TraceMemoryManagerStats(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime = true, bool recordPreGCUsage = true, @@ -203,7 +136,7 @@ public: bool recordGCEndTime = true, bool countCollection = true); - void initialize(bool fullGC, + void initialize(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime, bool recordPreGCUsage, @@ -213,7 +146,6 @@ public: bool recordGCEndTime, bool countCollection); - TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause); ~TraceMemoryManagerStats(); }; diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp index da25120bb37..9a1a4ae393d 100644 --- a/src/hotspot/share/services/threadService.cpp +++ b/src/hotspot/share/services/threadService.cpp @@ -34,9 +34,9 @@ #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" -#include "runtime/thread.hpp" -#include "runtime/vframe.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.inline.hpp" +#include "runtime/vframe.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "services/threadService.hpp" @@ -148,7 +148,7 @@ void ThreadService::current_thread_exiting(JavaThread* jt) { // FIXME: JVMTI should call this function Handle ThreadService::get_current_contended_monitor(JavaThread* thread) { assert(thread != NULL, "should be non-NULL"); - assert(Threads_lock->owned_by_self(), "must grab Threads_lock or be at safepoint"); + debug_only(Thread::check_for_dangling_thread_pointer(thread);) ObjectMonitor *wait_obj = thread->current_waiting_monitor(); @@ -266,6 +266,7 @@ Handle ThreadService::dump_stack_traces(GrowableArray* threads, int num_snapshots = dump_result.num_snapshots(); assert(num_snapshots == num_threads, "Must have num_threads thread snapshots"); + assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot"); int i = 0; for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; i++, ts = ts->next()) { ThreadStackTrace* stacktrace = ts->get_stack_trace(); @@ -297,7 +298,9 @@ void ThreadService::reset_contention_time_stat(JavaThread* thread) { } // Find deadlocks involving object monitors and concurrent locks if concurrent_locks is true -DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) { +DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list, bool concurrent_locks) { + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); + // This code was modified from the original Threads::find_deadlocks code. int globalDfn = 0, thisDfn; ObjectMonitor* waitingToLockMonitor = NULL; @@ -306,15 +309,16 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) JavaThread *currentThread, *previousThread; int num_deadlocks = 0; - for (JavaThread* p = Threads::first(); p != NULL; p = p->next()) { - // Initialize the depth-first-number - p->set_depth_first_number(-1); + // Initialize the depth-first-number for each JavaThread. + JavaThreadIterator jti(t_list); + for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) { + jt->set_depth_first_number(-1); } DeadlockCycle* deadlocks = NULL; DeadlockCycle* last = NULL; DeadlockCycle* cycle = new DeadlockCycle(); - for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { + for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) { if (jt->depth_first_number() >= 0) { // this thread was already visited continue; @@ -339,9 +343,8 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) if (waitingToLockMonitor != NULL) { address currentOwner = (address)waitingToLockMonitor->owner(); if (currentOwner != NULL) { - currentThread = Threads::owning_thread_from_monitor_owner( - currentOwner, - false /* no locking needed */); + currentThread = Threads::owning_thread_from_monitor_owner(t_list, + currentOwner); if (currentThread == NULL) { // This function is called at a safepoint so the JavaThread // that owns waitingToLockMonitor should be findable, but @@ -366,6 +369,8 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) if (concurrent_locks) { if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) { oop threadObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); + // This JavaThread (if there is one) is protected by the + // ThreadsListSetter in VM_FindDeadlocks::doit(). currentThread = threadObj != NULL ? java_lang_Thread::thread(threadObj) : NULL; } else { currentThread = NULL; @@ -414,7 +419,7 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) return deadlocks; } -ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) { +ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL), _setter() { // Create a new ThreadDumpResult object and append to the list. // If GC happens before this function returns, Method* @@ -422,7 +427,7 @@ ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snap ThreadService::add_thread_dump(this); } -ThreadDumpResult::ThreadDumpResult(int num_threads) : _num_threads(num_threads), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) { +ThreadDumpResult::ThreadDumpResult(int num_threads) : _num_threads(num_threads), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL), _setter() { // Create a new ThreadDumpResult object and append to the list. // If GC happens before this function returns, oops // will be visited. @@ -467,6 +472,10 @@ void ThreadDumpResult::metadata_do(void f(Metadata*)) { } } +ThreadsList* ThreadDumpResult::t_list() { + return _setter.list(); +} + StackFrameInfo::StackFrameInfo(javaVFrame* jvf, bool with_lock_info) { _method = jvf->method(); _bci = jvf->bci(); @@ -683,6 +692,8 @@ void ConcurrentLocksDump::build_map(GrowableArray* aos_objects) { oop o = aos_objects->at(i); oop owner_thread_obj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(o); if (owner_thread_obj != NULL) { + // See comments in ThreadConcurrentLocks to see how this + // JavaThread* is protected. JavaThread* thread = java_lang_Thread::thread(owner_thread_obj); assert(o->is_instance(), "Must be an instanceOop"); add_lock(thread, (instanceOop) o); @@ -764,7 +775,7 @@ ThreadStatistics::ThreadStatistics() { memset((void*) _perf_recursion_counts, 0, sizeof(_perf_recursion_counts)); } -ThreadSnapshot::ThreadSnapshot(JavaThread* thread) { +ThreadSnapshot::ThreadSnapshot(ThreadsList * t_list, JavaThread* thread) { _thread = thread; _threadObj = thread->threadObj(); _stack_trace = NULL; @@ -796,7 +807,7 @@ ThreadSnapshot::ThreadSnapshot(JavaThread* thread) { _thread_status = java_lang_Thread::RUNNABLE; } else { _blocker_object = obj(); - JavaThread* owner = ObjectSynchronizer::get_lock_owner(obj, false); + JavaThread* owner = ObjectSynchronizer::get_lock_owner(t_list, obj); if ((owner == NULL && _thread_status == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER) || (owner != NULL && owner->is_attaching_via_jni())) { // ownership information of the monitor is not available @@ -865,7 +876,7 @@ DeadlockCycle::~DeadlockCycle() { delete _threads; } -void DeadlockCycle::print_on(outputStream* st) const { +void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const { st->cr(); st->print_cr("Found one Java-level deadlock:"); st->print("============================="); @@ -895,9 +906,8 @@ void DeadlockCycle::print_on(outputStream* st) const { // No Java object associated - a JVMTI raw monitor owner_desc = " (JVMTI raw monitor),\n which is held by"; } - currentThread = Threads::owning_thread_from_monitor_owner( - (address)waitingToLockMonitor->owner(), - false /* no locking needed */); + currentThread = Threads::owning_thread_from_monitor_owner(t_list, + (address)waitingToLockMonitor->owner()); if (currentThread == NULL) { // The deadlock was detected at a safepoint so the JavaThread // that owns waitingToLockMonitor should be findable, but @@ -915,6 +925,7 @@ void DeadlockCycle::print_on(outputStream* st) const { "Must be an AbstractOwnableSynchronizer"); oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); currentThread = java_lang_Thread::thread(ownerObj); + assert(currentThread != NULL, "AbstractOwnableSynchronizer owning thread is unexpectedly NULL"); } st->print("%s \"%s\"", owner_desc, currentThread->get_thread_name()); } @@ -943,9 +954,7 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread, int init_size = ThreadService::get_live_thread_count(); _threads_array = new GrowableArray(init_size); - MutexLockerEx ml(Threads_lock); - - for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { // skips JavaThreads in the process of exiting // and also skips VM internal JavaThreads // Threads in _thread_new or _thread_new_trans state are included. diff --git a/src/hotspot/share/services/threadService.hpp b/src/hotspot/share/services/threadService.hpp index 46bc012f73e..950482e462d 100644 --- a/src/hotspot/share/services/threadService.hpp +++ b/src/hotspot/share/services/threadService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ #include "runtime/objectMonitor.hpp" #include "runtime/objectMonitor.inline.hpp" #include "runtime/perfData.hpp" +#include "runtime/thread.hpp" #include "services/management.hpp" #include "services/serviceUtil.hpp" @@ -109,7 +110,7 @@ public: static void reset_contention_count_stat(JavaThread* thread); static void reset_contention_time_stat(JavaThread* thread); - static DeadlockCycle* find_deadlocks_at_safepoint(bool object_monitors_only); + static DeadlockCycle* find_deadlocks_at_safepoint(ThreadsList * t_list, bool object_monitors_only); // GC support static void oops_do(OopClosure* f); @@ -189,6 +190,8 @@ public: // Thread snapshot to represent the thread state and statistics class ThreadSnapshot : public CHeapObj { private: + // This JavaThread* is protected by being stored in objects that are + // protected by a ThreadsListSetter (ThreadDumpResult). JavaThread* _thread; oop _threadObj; java_lang_Thread::ThreadStatus _thread_status; @@ -213,7 +216,7 @@ public: // Dummy snapshot ThreadSnapshot() : _thread(NULL), _threadObj(NULL), _stack_trace(NULL), _concurrent_locks(NULL), _next(NULL), _blocker_object(NULL), _blocker_object_owner(NULL) {}; - ThreadSnapshot(JavaThread* thread); + ThreadSnapshot(ThreadsList * t_list, JavaThread* thread); ~ThreadSnapshot(); java_lang_Thread::ThreadStatus thread_status() { return _thread_status; } @@ -310,6 +313,12 @@ class ThreadConcurrentLocks : public CHeapObj { private: GrowableArray* _owned_locks; ThreadConcurrentLocks* _next; + // This JavaThread* is protected in one of two different ways + // depending on the usage of the ThreadConcurrentLocks object: + // 1) by being stored in objects that are only allocated and used at a + // safepoint (ConcurrentLocksDump), or 2) by being stored in objects + // that are protected by a ThreadsListSetter (ThreadSnapshot inside + // ThreadDumpResult). JavaThread* _thread; public: ThreadConcurrentLocks(JavaThread* thread); @@ -333,8 +342,12 @@ class ConcurrentLocksDump : public StackObj { void add_lock(JavaThread* thread, instanceOop o); public: - ConcurrentLocksDump(bool retain_map_on_free) : _map(NULL), _last(NULL), _retain_map_on_free(retain_map_on_free) {}; - ConcurrentLocksDump() : _map(NULL), _last(NULL), _retain_map_on_free(false) {}; + ConcurrentLocksDump(bool retain_map_on_free) : _map(NULL), _last(NULL), _retain_map_on_free(retain_map_on_free) { + assert(SafepointSynchronize::is_at_safepoint(), "Must be constructed at a safepoint."); + }; + ConcurrentLocksDump() : _map(NULL), _last(NULL), _retain_map_on_free(false) { + assert(SafepointSynchronize::is_at_safepoint(), "Must be constructed at a safepoint."); + }; ~ConcurrentLocksDump(); void dump_at_safepoint(); @@ -349,6 +362,9 @@ class ThreadDumpResult : public StackObj { ThreadSnapshot* _snapshots; ThreadSnapshot* _last; ThreadDumpResult* _next; + ThreadsListSetter _setter; // Helper to set hazard ptr in the originating thread + // which protects the JavaThreads in _snapshots. + public: ThreadDumpResult(); ThreadDumpResult(int num_threads); @@ -360,6 +376,9 @@ class ThreadDumpResult : public StackObj { int num_threads() { return _num_threads; } int num_snapshots() { return _num_snapshots; } ThreadSnapshot* snapshots() { return _snapshots; } + void set_t_list() { _setter.set(); } + ThreadsList* t_list(); + bool t_list_has_been_set() { return _setter.target_needs_release(); } void oops_do(OopClosure* f); void metadata_do(void f(Metadata*)); }; @@ -381,7 +400,7 @@ class DeadlockCycle : public CHeapObj { bool is_deadlock() { return _is_deadlock; } int num_threads() { return _threads->length(); } GrowableArray* threads() { return _threads; } - void print_on(outputStream* st) const; + void print_on_with(ThreadsList * t_list, outputStream* st) const; }; // Utility class to get list of java threads. diff --git a/src/hotspot/share/utilities/decoder.cpp b/src/hotspot/share/utilities/decoder.cpp index 61a274c68fb..38ba9decb6e 100644 --- a/src/hotspot/share/utilities/decoder.cpp +++ b/src/hotspot/share/utilities/decoder.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "jvm.h" +#include "memory/allocation.inline.hpp" #include "runtime/os.hpp" #include "utilities/decoder.hpp" #include "utilities/vmError.hpp" diff --git a/src/hotspot/share/utilities/decoder_elf.cpp b/src/hotspot/share/utilities/decoder_elf.cpp index cd438dc1c49..c8639c2b972 100644 --- a/src/hotspot/share/utilities/decoder_elf.cpp +++ b/src/hotspot/share/utilities/decoder_elf.cpp @@ -26,6 +26,7 @@ #if !defined(_WINDOWS) && !defined(__APPLE__) #include "decoder_elf.hpp" +#include "memory/allocation.inline.hpp" ElfDecoder::~ElfDecoder() { if (_opened_elf_files != NULL) { diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 33f9962da15..e98ec391144 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -951,7 +951,6 @@ const int badResourceValue = 0xAB; // value used to zap const int freeBlockPad = 0xBA; // value used to pad freed blocks. const int uninitBlockPad = 0xF1; // value used to zap newly malloc'd blocks. const juint uninitMetaWordVal= 0xf7f7f7f7; // value used to zap newly allocated metachunk -const intptr_t badJNIHandleVal = (intptr_t) UCONST64(0xFEFEFEFEFEFEFEFE); // value used to zap jni handle area const juint badHeapWordVal = 0xBAADBABE; // value used to zap heap after GC const juint badMetaWordVal = 0xBAADFADE; // value used to zap metadata heap after GC const int badCodeHeapNewVal= 0xCC; // value used to zap Code heap at allocation @@ -963,7 +962,6 @@ const int badCodeHeapFreeVal = 0xDD; // value used to zap #define badAddress ((address)::badAddressVal) #define badOop (cast_to_oop(::badOopVal)) #define badHeapWord (::badHeapWordVal) -#define badJNIHandle (cast_to_oop(::badJNIHandleVal)) // Default TaskQueue size is 16K (32-bit) or 128K (64-bit) #define TASKQUEUE_SIZE (NOT_LP64(1<<14) LP64_ONLY(1<<17)) diff --git a/src/hotspot/share/utilities/growableArray.cpp b/src/hotspot/share/utilities/growableArray.cpp index d6dc256a2c7..076529897c6 100644 --- a/src/hotspot/share/utilities/growableArray.cpp +++ b/src/hotspot/share/utilities/growableArray.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/thread.inline.hpp" #include "utilities/growableArray.hpp" @@ -56,3 +57,7 @@ void* GenericGrowableArray::raw_allocate(int elementSize) { return _arena->Amalloc(byte_size); } } + +void GenericGrowableArray::free_C_heap(void* elements) { + FreeHeap(elements); +} diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp index f65f45cede7..4c5a4914db7 100644 --- a/src/hotspot/share/utilities/growableArray.hpp +++ b/src/hotspot/share/utilities/growableArray.hpp @@ -26,9 +26,9 @@ #define SHARE_VM_UTILITIES_GROWABLEARRAY_HPP #include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" // A growable array. @@ -144,6 +144,8 @@ class GenericGrowableArray : public ResourceObj { assert(on_stack(), "fast ResourceObj path only"); return (void*)resource_allocate_bytes(thread, elementSize * _max); } + + void free_C_heap(void* elements); }; template class GrowableArrayIterator; @@ -451,7 +453,7 @@ template void GrowableArray::grow(int j) { for ( ; i < _max; i++) ::new ((void*)&newData[i]) E(); for (i = 0; i < old_max; i++) _data[i].~E(); if (on_C_heap() && _data != NULL) { - FreeHeap(_data); + free_C_heap(_data); } _data = newData; } @@ -475,7 +477,7 @@ template void GrowableArray::clear_and_deallocate() { clear(); if (_data != NULL) { for (int i = 0; i < _max; i++) _data[i].~E(); - FreeHeap(_data); + free_C_heap(_data); _data = NULL; } } diff --git a/src/hotspot/share/utilities/stack.hpp b/src/hotspot/share/utilities/stack.hpp index 7c866897691..b606bce533a 100644 --- a/src/hotspot/share/utilities/stack.hpp +++ b/src/hotspot/share/utilities/stack.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_STACK_HPP #include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" // Class Stack (below) grows and shrinks by linking together "segments" which // are allocated on demand. Segments are arrays of the element type (E) plus an diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 580fc86e89e..8d127605e13 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -36,6 +36,7 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "runtime/vm_version.hpp" @@ -1655,7 +1656,12 @@ void VMError::controlled_crash(int how) { char * const dataPtr = NULL; // bad data pointer const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer - // Keep this in sync with test/runtime/ErrorHandling/ErrorHandler.java + // Keep this in sync with test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java + // which tests cases 1 thru 13. + // Case 14 is tested by test/hotspot/jtreg/runtime/ErrorHandling/SafeFetchInErrorHandlingTest.java. + // Case 15 is tested by test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java. + // Case 16 is tested by test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java. + // Case 17 is tested by test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java. switch (how) { case 1: vmassert(str == NULL, "expected null"); case 2: vmassert(num == 1023 && *str == 'X', @@ -1683,6 +1689,17 @@ void VMError::controlled_crash(int how) { case 13: (*funcPtr)(); break; case 14: crash_with_segfault(); break; case 15: crash_with_sigfpe(); break; + case 16: { + ThreadsListHandle tlh; + fatal("Force crash with an active ThreadsListHandle."); + } + case 17: { + ThreadsListHandle tlh; + { + ThreadsListHandle tlh2; + fatal("Force crash with a nested ThreadsListHandle."); + } + } default: tty->print_cr("ERROR: %d: unexpected test_num value.", how); } diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy index c5d6fd9bf9b..a4a9cbcbccc 100644 --- a/src/java.base/share/lib/security/default.policy +++ b/src/java.base/share/lib/security/default.policy @@ -155,7 +155,10 @@ grant codeBase "jrt:/jdk.internal.vm.compiler" { }; grant codeBase "jrt:/jdk.internal.vm.compiler.management" { - permission java.security.AllPermission; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.hotspot"; + permission java.lang.RuntimePermission "accessClassInPackage.jdk.vm.ci.runtime"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.management.spi"; + permission java.lang.RuntimePermission "sun.management.spi.PlatformMBeanProvider.subclass"; }; grant codeBase "jrt:/jdk.jsobject" { diff --git a/src/java.management/share/classes/com/sun/jmx/remote/security/FileLoginModule.java b/src/java.management/share/classes/com/sun/jmx/remote/security/FileLoginModule.java index 9c5ebb6ec85..79b6dcf3b43 100644 --- a/src/java.management/share/classes/com/sun/jmx/remote/security/FileLoginModule.java +++ b/src/java.management/share/classes/com/sun/jmx/remote/security/FileLoginModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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,22 +22,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package com.sun.jmx.remote.security; import com.sun.jmx.mbeanserver.GetPropertyAction; import com.sun.jmx.mbeanserver.Util; -import java.io.BufferedInputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FilePermission; import java.io.IOException; import java.security.AccessControlException; import java.security.AccessController; import java.util.Arrays; -import java.util.Hashtable; import java.util.Map; -import java.util.Properties; import javax.security.auth.*; import javax.security.auth.callback.*; @@ -59,10 +54,7 @@ import com.sun.jmx.remote.util.EnvHelp; * the access control file for JMX remote management or in a Java security * policy. * - *

The password file comprises a list of key-value pairs as specified in - * {@link Properties}. The key represents a user's name and the value is its - * associated cleartext password. By default, the following password file is - * used: + * By default, the following password file is used: *

  *     ${java.home}/conf/management/jmxremote.password
  * 
@@ -105,6 +97,11 @@ import com.sun.jmx.remote.util.EnvHelp; *
if true, this module clears the username and password * stored in the module's shared state after both phases of authentication * (login and commit) have completed.
+ * + *
hashPasswords
+ *
if true, this module replaces each clear text password + * with its hash, if present.
+ * * */ public class FileLoginModule implements LoginModule { @@ -135,6 +132,7 @@ public class FileLoginModule implements LoginModule { private boolean tryFirstPass = false; private boolean storePass = false; private boolean clearPass = false; + private boolean hashPasswords = false; // Authentication status private boolean succeeded = false; @@ -154,7 +152,7 @@ public class FileLoginModule implements LoginModule { private String passwordFileDisplayName; private boolean userSuppliedPasswordFile; private boolean hasJavaHomePermission; - private Properties userCredentials; + private HashedPasswordManager hashPwdMgr; /** * Initialize this LoginModule. @@ -186,6 +184,8 @@ public class FileLoginModule implements LoginModule { "true".equalsIgnoreCase((String)options.get("storePass")); clearPass = "true".equalsIgnoreCase((String)options.get("clearPass")); + hashPasswords + = "true".equalsIgnoreCase((String) options.get("hashPasswords")); passwordFile = (String)options.get("passwordFile"); passwordFileDisplayName = passwordFile; @@ -221,17 +221,28 @@ public class FileLoginModule implements LoginModule { public boolean login() throws LoginException { try { - loadPasswordFile(); + synchronized (this) { + if (hashPwdMgr == null) { + hashPwdMgr = new HashedPasswordManager(passwordFile, hashPasswords); + } + } + hashPwdMgr.loadPasswords(); } catch (IOException ioe) { LoginException le = new LoginException( "Error: unable to load the password file: " + passwordFileDisplayName); throw EnvHelp.initCause(le, ioe); - } - - if (userCredentials == null) { - throw new LoginException - ("Error: unable to locate the users' credentials."); + } catch (SecurityException e) { + if (userSuppliedPasswordFile || hasJavaHomePermission) { + throw e; + } else { + final FilePermission fp + = new FilePermission(passwordFileDisplayName, "read"); + AccessControlException ace = new AccessControlException( + "access denied " + fp.toString()); + ace.initCause(e); + throw ace; + } } if (logger.debugOn()) { @@ -437,12 +448,7 @@ public class FileLoginModule implements LoginModule { // get the username and password getUsernamePassword(usePasswdFromSharedState); - String localPassword; - - // userCredentials is initialized in login() - if (((localPassword = userCredentials.getProperty(username)) == null) || - (! localPassword.equals(new String(password)))) { - + if (!hashPwdMgr.authenticate(username, password)) { // username not found or passwords do not match if (logger.debugOn()) { logger.debug("login", "Invalid username or password"); @@ -468,38 +474,6 @@ public class FileLoginModule implements LoginModule { } } - /* - * Read the password file. - */ - private void loadPasswordFile() throws IOException { - FileInputStream fis; - try { - fis = new FileInputStream(passwordFile); - } catch (SecurityException e) { - if (userSuppliedPasswordFile || hasJavaHomePermission) { - throw e; - } else { - final FilePermission fp = - new FilePermission(passwordFileDisplayName, "read"); - AccessControlException ace = new AccessControlException( - "access denied " + fp.toString()); - ace.setStackTrace(e.getStackTrace()); - throw ace; - } - } - try { - final BufferedInputStream bis = new BufferedInputStream(fis); - try { - userCredentials = new Properties(); - userCredentials.load(bis); - } finally { - bis.close(); - } - } finally { - fis.close(); - } - } - /** * Get the username and password. * This method does not return any value. diff --git a/src/java.management/share/classes/com/sun/jmx/remote/security/HashedPasswordManager.java b/src/java.management/share/classes/com/sun/jmx/remote/security/HashedPasswordManager.java new file mode 100644 index 00000000000..1404e2d458e --- /dev/null +++ b/src/java.management/share/classes/com/sun/jmx/remote/security/HashedPasswordManager.java @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2017, 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 com.sun.jmx.remote.security; + +import com.sun.jmx.remote.util.ClassLogger; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.FileLock; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * HashedPasswordManager loads passwords from the password file and optionally + * hashes them. + *

+ *

+ * This class accepts Unicode UTF-8 encoded file + *

+ *

+ * Each entry in the password file contains a username followed by a password. + * Password can be in clear text or as a hash. Hashed passwords must follow the + * below format. hashedPassword = base64_encoded_64_byte_salt W + * base64_encoded_hash W hash_algorithm where, W = spaces, + * base64_encoded_64_byte_salt = 64 byte random salt, base64_encoded_hash = + * hash_algorithm(password + salt), hash_algorithm = Algorithm string as + * specified in + * + * + * hash_algorithm is an optional field. If not specified, SHA3-512 will be + * assumed. + *

+ *

+ * If passwords are in clear, they will be over-written by their hash if hashing + * is requested by setting com.sun.management.jmxremote.password.toHashes + * property to true in the management.properties file and if the password file + * is writable and if the system security policy allows writing into the + * password file, if a security manager is configured + *

+ *

+ * In order to change the password for a role, replace the hashed password entry + * with a new clear text password or a new hashed password. If the new password + * is in clear, it will be replaced with its hash when a new login attempt is + * made. + *

+ *

+ * A given role should have at most one entry in this file. If a role has no + * entry, it has no access. If multiple entries are found for the same role + * name, then the last one will be used. + *

+ *

+ *

+ * A user generated hashed password file can also be used instead of a + * clear-text password file. If generated by the user, hashed passwords must + * follow the format specified above. + */ +final public class HashedPasswordManager { + + private static final class UserCredentials { + + private final String userName; + private final String hashAlgorithm; + private final String b64Salt; + private final String b64Hash; + + public UserCredentials(String userName, String hashAlgorithm, String b64Salt, String b64Hash) { + this.userName = userName; + this.hashAlgorithm = hashAlgorithm; + this.b64Salt = b64Salt; + this.b64Hash = b64Hash; + } + + @Override + public String toString() { + return userName + " " + b64Salt + " " + b64Hash + " " + hashAlgorithm; + } + } + + private static final String DefaultHashAlgorithm = "SHA3-512"; + private static final int DefaultSaltLength = 64; + + private final SecureRandom random = new SecureRandom(); + private final Map userCredentialsMap = new HashMap<>(); + private final String passwordFile; + private final boolean shouldHashPasswords; + private boolean isLogged = false; + + private static final ClassLogger logger + = new ClassLogger("javax.management.remote.misc", + "HashedPasswordManager"); + + /** + * Creates a new password manager for the input password file + * + * @param filename UTF-8 encoded input file to read passwords from + * @param shouldHashPasswords Request for clear passwords to be hashed + */ + public HashedPasswordManager(String filename, boolean shouldHashPasswords) { + this.passwordFile = filename; + this.shouldHashPasswords = shouldHashPasswords; + } + + private String[] getHash(String algorithm, String password) { + try { + byte[] salt = new byte[DefaultSaltLength]; + random.nextBytes(salt); + + MessageDigest digest = MessageDigest.getInstance(algorithm); + digest.reset(); + digest.update(salt); + byte[] hash = digest.digest(password.getBytes(StandardCharsets.UTF_8)); + String saltStr = Base64.getEncoder().encodeToString(salt); + String hashStr = Base64.getEncoder().encodeToString(hash); + + return new String[]{saltStr, hashStr}; + } catch (NoSuchAlgorithmException ex) { + if (logger.debugOn()) { + logger.debug("getHash", "Invalid algorithm : " + algorithm); + } + // We should never reach here as default Hash Algorithm + // must be always present + return new String[]{"", ""}; + } + } + + private String[] readPasswordFile() throws IOException { + synchronized (HashedPasswordManager.class) { + byte[] data; + File f = new File(passwordFile); + try (FileInputStream fin = new FileInputStream(f); + FileLock lock = fin.getChannel().lock(0L, Long.MAX_VALUE, true)) { + data = new byte[(int) f.length()]; + int read = fin.read(data); + if (read != data.length) { + throw new IOException("Failed to read data from the password file"); + } + lock.release(); + } + String str = new String(data, StandardCharsets.UTF_8); + return str.split("\\r?\\n"); + } + } + + private void writePasswordFile(String input) throws IOException { + synchronized (HashedPasswordManager.class) { + try (FileOutputStream fout = new FileOutputStream(passwordFile); + OutputStreamWriter out = new OutputStreamWriter(fout, StandardCharsets.UTF_8); + FileLock lock = fout.getChannel().lock()) { + out.write(input); + lock.release(); + } + } + } + + /** + * Authenticate the supplied credentials against the one present in the file + * + * @param userName Input username + * @param inputPassword Input password + * @return true if authentication succeeds, false otherwise + */ + public synchronized boolean authenticate(String userName, char[] inputPassword) { + if (userCredentialsMap.containsKey(userName)) { + try { + UserCredentials us = userCredentialsMap.get(userName); + byte[] salt = Base64.getDecoder().decode(us.b64Salt); + byte[] targetHash = Base64.getDecoder().decode(us.b64Hash); + MessageDigest digest = MessageDigest.getInstance(us.hashAlgorithm); + digest.reset(); + digest.update(salt); + ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(CharBuffer.wrap(inputPassword)); + byte[] passwordBytes = new byte[byteBuffer.limit()]; + byteBuffer.get(passwordBytes); + byte[] hash = digest.digest(passwordBytes); + return Arrays.equals(hash, targetHash); + } catch (NoSuchAlgorithmException ex) { + if (logger.debugOn()) { + logger.debug("authenticate", "Unrecognized hash algorithm : " + + userCredentialsMap.get(userName).hashAlgorithm + + " - for user : " + userName); + } + return false; + } + } else { + if (logger.debugOn()) { + logger.debug("authenticate", "Unknown user : " + userName); + } + return false; + } + } + + /** + * Load passwords from the password file. + *

+ *

+ * This method should be called for every login attempt to load new/changed + * credentials, if any. + *

+ *

+ * If hashing is requested, clear passwords will be over-written with their + * SHA3-512 hash + * + * @throws IOException If unable to access the file + * @throws SecurityException If read/write file permissions are not granted + */ + public synchronized void loadPasswords() + throws IOException, SecurityException { + + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkRead(passwordFile); + } + + AtomicBoolean hasClearPasswords = new AtomicBoolean(false); + StringBuilder sbuf = new StringBuilder(); + final String header = "# The passwords in this file are hashed.\n" + + "# In order to change the password for a role, replace the hashed " + + "password entry\n" + + "# with a clear text password or a new hashed password. " + + "If the new password is in clear,\n# it will be replaced with its " + + "hash when a new login attempt is made.\n\n"; + + userCredentialsMap.clear(); + Arrays.stream(readPasswordFile()).forEach(line -> { + if (line.trim().startsWith("#")) { // Ignore comments + sbuf.append(line).append("\n"); + return; + } + String[] tokens = line.split("\\s+"); + switch (tokens.length) { + case 2: { + // Password is in clear + String[] b64str = getHash(DefaultHashAlgorithm, tokens[1]); + UserCredentials us = new UserCredentials(tokens[0], DefaultHashAlgorithm, b64str[0], b64str[1]); + sbuf.append(us.userName).append(" ").append(us.b64Salt). + append(" ").append(us.b64Hash).append(" "). + append(us.hashAlgorithm).append("\n"); + if (userCredentialsMap.get(tokens[0]) != null) { + if (logger.debugOn()) { + logger.debug("loadPasswords", "Ignoring entry for role : " + tokens[0]); + } + } + userCredentialsMap.put(tokens[0], us); + hasClearPasswords.set(true); + if (logger.debugOn()) { + logger.debug("loadPasswords", + "Found atleast one clear password"); + } + break; + } + case 3: + case 4: { + // Passwords are hashed + UserCredentials us = new UserCredentials(tokens[0], (tokens.length == 4 ? tokens[3] : DefaultHashAlgorithm), + tokens[1], tokens[2]); + sbuf.append(line).append("\n"); + if (userCredentialsMap.get(tokens[0]) != null) { + if (logger.debugOn()) { + logger.debug("loadPasswords", "Ignoring entry for role : " + tokens[0]); + } + } + userCredentialsMap.put(tokens[0], us); + break; + } + default: + sbuf.append(line).append("\n"); + break; + } + }); + + if (!shouldHashPasswords && hasClearPasswords.get()) { + if (logger.debugOn()) { + logger.debug("loadPasswords", + "Passwords in " + passwordFile + " are in clear but are requested " + + "not to be hashed !!!"); + } + } + + // Check if header needs to be inserted + if (sbuf.indexOf("# The passwords in this file are hashed") != 0) { + sbuf.insert(0, header); + } + + // Even if we are unable to write hashed passwords to password file, + // passwords will be hashed in memory so that jvm heap dump should not + // give away clear passwords + if (shouldHashPasswords && hasClearPasswords.get()) { + if (new File(passwordFile).canWrite()) { + writePasswordFile(sbuf.toString()); + if (logger.debugOn()) { + logger.debug("loadPasswords", + "Wrote hashed passwords to file : " + passwordFile); + } + } else if (logger.debugOn() && !isLogged) { + isLogged = true; + logger.debug("loadPasswords", + "Passwords in " + passwordFile + " are in clear and password file is read-only. " + + "Passwords cannot be hashed !!!!"); + } + } + } +} diff --git a/src/java.management/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java b/src/java.management/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java index f7ab5d70fb6..dadef33e5dc 100644 --- a/src/java.management/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java +++ b/src/java.management/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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,8 +34,6 @@ import java.security.PrivilegedExceptionAction; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.Properties; -import javax.management.remote.JMXPrincipal; import javax.management.remote.JMXAuthenticator; import javax.security.auth.AuthPermission; import javax.security.auth.Subject; @@ -91,10 +89,12 @@ public final class JMXPluggableAuthenticator implements JMXAuthenticator { String loginConfigName = null; String passwordFile = null; + String hashPasswords = null; if (env != null) { loginConfigName = (String) env.get(LOGIN_CONFIG_PROP); passwordFile = (String) env.get(PASSWORD_FILE_PROP); + hashPasswords = (String) env.get(HASH_PASSWORDS); } try { @@ -114,6 +114,7 @@ public final class JMXPluggableAuthenticator implements JMXAuthenticator { } final String pf = passwordFile; + final String hashPass = hashPasswords; try { loginContext = AccessController.doPrivileged( new PrivilegedExceptionAction() { @@ -122,7 +123,7 @@ public final class JMXPluggableAuthenticator implements JMXAuthenticator { LOGIN_CONFIG_NAME, null, new JMXCallbackHandler(), - new FileLoginConfig(pf)); + new FileLoginConfig(pf, hashPass)); } }); } catch (PrivilegedActionException pae) { @@ -250,6 +251,8 @@ public final class JMXPluggableAuthenticator implements JMXAuthenticator { private static final String LOGIN_CONFIG_NAME = "JMXPluggableAuthenticator"; private static final String PASSWORD_FILE_PROP = "jmx.remote.x.password.file"; + private static final String HASH_PASSWORDS = + "jmx.remote.x.password.toHashes"; private static final ClassLogger logger = new ClassLogger("javax.management.remote.misc", LOGIN_CONFIG_NAME); @@ -303,19 +306,22 @@ private static class FileLoginConfig extends Configuration { // The option that identifies the password file to use private static final String PASSWORD_FILE_OPTION = "passwordFile"; + private static final String HASH_PASSWORDS = "hashPasswords"; /** * Creates an instance of FileLoginConfig * * @param passwordFile A filepath that identifies the password file to use. * If null then the default password file is used. + * @param hashPasswords Flag to indicate if the password file needs to be hashed */ - public FileLoginConfig(String passwordFile) { + public FileLoginConfig(String passwordFile, String hashPasswords) { Map options; if (passwordFile != null) { options = new HashMap(1); options.put(PASSWORD_FILE_OPTION, passwordFile); + options.put(HASH_PASSWORDS, hashPasswords); } else { options = Collections.emptyMap(); } diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java index 0971479577e..b0e8799559f 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java @@ -65,6 +65,8 @@ public final class BinaryContainer implements SymbolTable { private final int codeEntryAlignment; + private final boolean threadLocalHandshakes; + /** * Container holding code bits and any other related information. */ @@ -279,6 +281,8 @@ public final class BinaryContainer implements SymbolTable { this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment; + this.threadLocalHandshakes = graalHotSpotVMConfig.threadLocalHandshakes; + // Section unique name is limited to 8 characters due to limitation on Windows. // Name could be longer but only first 8 characters are stored on Windows. @@ -323,7 +327,8 @@ public final class BinaryContainer implements SymbolTable { TieredAOT.getValue(graalOptions), graalHotSpotVMConfig.enableContended, graalHotSpotVMConfig.restrictContended, - graphBuilderConfig.omitAssertions() + graphBuilderConfig.omitAssertions(), + graalHotSpotVMConfig.threadLocalHandshakes }; int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().getShift(), @@ -434,6 +439,11 @@ public final class BinaryContainer implements SymbolTable { return codeEntryAlignment; } + public boolean getThreadLocalHandshakes() { + return threadLocalHandshakes; + } + + /** * Gets the global AOT symbol associated with the function name. * diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java index 397d86e7378..16d5dadffc5 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java @@ -45,6 +45,7 @@ final class MarkProcessor { * @param methodInfo compiled method info * @param mark mark being processed */ + @SuppressWarnings("fallthrough") void process(CompiledMethodInfo methodInfo, Mark mark) { MarkId markId = MarkId.getEnum((int) mark.id); switch (markId) { @@ -53,6 +54,11 @@ final class MarkProcessor { break; case POLL_FAR: case POLL_RETURN_FAR: + if (binaryContainer.getThreadLocalHandshakes()) { + // skip relocation + break; + } + // fallthrough case CARD_TABLE_ADDRESS: case HEAP_TOP_ADDRESS: case HEAP_END_ADDRESS: diff --git a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java index 9ab9357ad05..a475bf42a38 100644 --- a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java +++ b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java @@ -86,18 +86,23 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine { private void loadAgentLibrary(String agentLibrary, boolean isAbsolute, String options) throws AgentLoadException, AgentInitializationException, IOException { + String msgPrefix = "return code: "; InputStream in = execute("load", agentLibrary, isAbsolute ? "true" : "false", options); - try { - int result = readInt(in); - if (result != 0) { - throw new AgentInitializationException("Agent_OnAttach failed", result); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { + String result = reader.readLine(); + if (result == null) { + throw new AgentLoadException("Target VM did not respond"); + } else if (result.startsWith(msgPrefix)) { + int retCode = Integer.parseInt(result.substring(msgPrefix.length())); + if (retCode != 0) { + throw new AgentInitializationException("Agent_OnAttach failed", retCode); + } + } else { + throw new AgentLoadException(result); } - } finally { - in.close(); - } } diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/BsdDebuggerLocal.c b/src/jdk.hotspot.agent/macosx/native/libsaproc/BsdDebuggerLocal.c index 85b07f76440..fadf211ac0f 100644 --- a/src/jdk.hotspot.agent/macosx/native/libsaproc/BsdDebuggerLocal.c +++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/BsdDebuggerLocal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -298,9 +298,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_ #ifdef i386 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #endif -#ifdef ia64 -#define NPRGREG IA64_REG_COUNT -#endif #ifdef amd64 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG #endif @@ -335,14 +332,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_ #endif /* i386 */ -#if ia64 - regs = (*env)->GetLongArrayElements(env, array, &isCopy); - int i; - for (i = 0; i < NPRGREG; i++ ) { - regs[i] = 0xDEADDEAD; - } -#endif /* ia64 */ - #ifdef amd64 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java index bb92d20b1c8..33f20eadbb8 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ import sun.jvm.hotspot.debugger.MachineDescription; import sun.jvm.hotspot.debugger.MachineDescriptionAMD64; import sun.jvm.hotspot.debugger.MachineDescriptionPPC64; import sun.jvm.hotspot.debugger.MachineDescriptionAArch64; -import sun.jvm.hotspot.debugger.MachineDescriptionIA64; import sun.jvm.hotspot.debugger.MachineDescriptionIntelX86; import sun.jvm.hotspot.debugger.MachineDescriptionSPARC32Bit; import sun.jvm.hotspot.debugger.MachineDescriptionSPARC64Bit; @@ -556,10 +555,8 @@ public class HotSpotAgent { machDesc = new MachineDescriptionIntelX86(); } else if (cpu.equals("amd64")) { machDesc = new MachineDescriptionAMD64(); - } else if (cpu.equals("ia64")) { - machDesc = new MachineDescriptionIA64(); } else { - throw new DebuggerException("Win32 supported under x86, amd64 and ia64 only"); + throw new DebuggerException("Win32 supported under x86 and amd64 only"); } // Note we do not use a cache for the local debugger in server @@ -586,8 +583,6 @@ public class HotSpotAgent { if (cpu.equals("x86")) { machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("ia64")) { - machDesc = new MachineDescriptionIA64(); } else if (cpu.equals("amd64")) { machDesc = new MachineDescriptionAMD64(); } else if (cpu.equals("ppc64")) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java index 45697a83808..655b450c3fc 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -216,11 +216,7 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger { // the UI. This is a cache of 4096 4K pages, or 16 MB. The page // size must be adjusted to be the hardware's page size. // (FIXME: should pick this up from the debugger.) - if (getCPU().equals("ia64")) { - initCache(16384, parseCacheNumPagesProperty(1024)); - } else { - initCache(4096, parseCacheNumPagesProperty(4096)); - } + initCache(4096, parseCacheNumPagesProperty(4096)); } isDarwin = getOS().equals("darwin"); @@ -575,11 +571,6 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger { public CDebugger getCDebugger() { if (cdbg == null) { - String cpu = getCPU(); - if (cpu.equals("ia64") ) { - // IA-64 is not supported because of stack-walking issues - return null; - } cdbg = new BsdCDebugger(this); } return cdbg; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java deleted file mode 100644 index 8a8ce383f2e..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2003, 2012, 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.debugger.ia64; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; - -/** Specifies the thread context on ia64 platform; only a sub-portion - of the context is guaranteed to be present on all operating - systems. */ - -public abstract class IA64ThreadContext implements ThreadContext { - // Refer to winnt.h CONTEXT structure - Nov 2001 edition Platform SDK - // only a relevant subset of CONTEXT structure is used here. - // For eg. floating point registers are ignored. - - // NOTE: the indices for the various registers must be maintained as - // listed across various operating systems. However, only a - // subset of the registers' values are guaranteed to be present - - // global registers r0-r31 - public static final int GR0 = 0; - public static final int GR1 = 1; - public static final int GR2 = 2; - public static final int GR3 = 3; - public static final int GR4 = 4; - public static final int GR5 = 5; - public static final int GR6 = 6; - public static final int GR7 = 7; - public static final int GR8 = 8; - public static final int GR9 = 9; - public static final int GR10 = 10; - public static final int GR11 = 11; - public static final int GR12 = 12; - public static final int SP = GR12; - public static final int GR13 = 13; - public static final int GR14 = 14; - public static final int GR15 = 15; - public static final int GR16 = 16; - public static final int GR17 = 17; - public static final int GR18 = 18; - public static final int GR19 = 19; - public static final int GR20 = 20; - public static final int GR21 = 21; - public static final int GR22 = 22; - public static final int GR23 = 23; - public static final int GR24 = 24; - public static final int GR25 = 25; - public static final int GR26 = 26; - public static final int GR27 = 27; - public static final int GR28 = 28; - public static final int GR29 = 29; - public static final int GR30 = 30; - public static final int GR31 = 31; - - // Nat bits for r1-r31 - public static final int INT_NATS = 32; - - // predicates - public static final int PREDS = 33; - - // branch registers - public static final int BR0 = 34; - public static final int BR_RP = BR0; - public static final int BR1 = 35; - public static final int BR2 = 36; - public static final int BR3 = 37; - public static final int BR4 = 38; - public static final int BR5 = 39; - public static final int BR6 = 40; - public static final int BR7 = 41; - - // application registers - public static final int AP_UNAT = 42; // User Nat Collection register - public static final int AP_LC = 43; // Loop counter register - public static final int AP_EC = 43; // Epilog counter register - public static final int AP_CCV = 45; // CMPXCHG value register - public static final int AP_DCR = 46; // Default control register - - // register stack info - public static final int RS_PFS = 47; // Previous function state - public static final int AP_PFS = RS_PFS; - public static final int RS_BSP = 48; // Backing store pointer - public static final int AR_BSP = RS_BSP; - public static final int RS_BSPSTORE = 49; - public static final int AP_BSPSTORE = RS_BSPSTORE; - public static final int RS_RSC = 50; // RSE configuration - public static final int AP_RSC = RS_RSC; - public static final int RS_RNAT = 51; // RSE Nat collection register - public static final int AP_RNAT = RS_RNAT; - - // trap status register - public static final int ST_IPSR = 52; // Interuption Processor Status - public static final int ST_IIP = 53; // Interruption IP - public static final int ST_IFS = 54; // Interruption Function State - - // debug registers - public static final int DB_I0 = 55; - public static final int DB_I1 = 56; - public static final int DB_I2 = 57; - public static final int DB_I3 = 58; - public static final int DB_I4 = 59; - public static final int DB_I5 = 60; - public static final int DB_I6 = 61; - public static final int DB_I7 = 62; - - public static final int DB_D0 = 63; - public static final int DB_D1 = 64; - public static final int DB_D2 = 65; - public static final int DB_D3 = 66; - public static final int DB_D4 = 67; - public static final int DB_D5 = 68; - public static final int DB_D6 = 69; - public static final int DB_D7 = 70; - - public static final int NPRGREG = 71; - - private static final String[] regNames = { - "GR0", "GR1", "GR2", "GR3", "GR4", "GR5", "GR6", "GR7", "GR8", - "GR9", "GR10", "GR11", "GR12", "GR13", "GR14", "GR15", "GR16", - "GR17","GR18", "GR19", "GR20", "GR21", "GR22", "GR23", "GR24", - "GR25","GR26", "GR27", "GR28", "GR29", "GR30", "GR31", - "INT_NATS", "PREDS", - "BR0", "BR1", "BR2", "BR3", "BR4", "BR5", "BR6", "BR7", - "AP_UNAT", "AP_LC", "AP_EC", "AP_CCV", "AP_DCR", - "RS_FPS", "RS_BSP", "RS_BSPSTORE", "RS_RSC", "RS_RNAT", - "ST_IPSR", "ST_IIP", "ST_IFS", - "DB_I0", "DB_I1", "DB_I2", "DB_I3", "DB_I4", "DB_I5", "DB_I6", "DB_I7", - "DB_D0", "DB_D1", "DB_D2", "DB_D3", "DB_D4", "DB_D5", "DB_D6", "DB_D7" - }; - - private long[] data; - - public IA64ThreadContext() { - data = new long[NPRGREG]; - } - - public int getNumRegisters() { - return NPRGREG; - } - - public String getRegisterName(int index) { - return regNames[index]; - } - - public void setRegister(int index, long value) { - data[index] = value; - } - - public long getRegister(int index) { - return data[index]; - } - - public CFrame getTopFrame(Debugger dbg) { - return null; - } - - /** This can't be implemented in this class since we would have to - tie the implementation to, for example, the debugging system */ - public abstract void setRegisterAsAddress(int index, Address value); - - /** This can't be implemented in this class since we would have to - tie the implementation to, for example, the debugging system */ - public abstract Address getRegisterAsAddress(int index); -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java index f282a228df6..0d47eb03630 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -210,11 +210,7 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger { // the UI. This is a cache of 4096 4K pages, or 16 MB. The page // size must be adjusted to be the hardware's page size. // (FIXME: should pick this up from the debugger.) - if (getCPU().equals("ia64")) { - initCache(16384, parseCacheNumPagesProperty(1024)); - } else { - initCache(4096, parseCacheNumPagesProperty(4096)); - } + initCache(4096, parseCacheNumPagesProperty(4096)); } workerThread = new LinuxDebuggerLocalWorkerThread(this); @@ -560,11 +556,6 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger { public CDebugger getCDebugger() { if (cdbg == null) { - String cpu = getCPU(); - if (cpu.equals("ia64") ) { - // IA-64 is not supported because of stack-walking issues - return null; - } cdbg = new LinuxCDebugger(this); } return cdbg; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java index 2225558000b..4b786eecc95 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package sun.jvm.hotspot.debugger.linux; import java.lang.reflect.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.linux.amd64.*; -import sun.jvm.hotspot.debugger.linux.ia64.*; import sun.jvm.hotspot.debugger.linux.x86.*; import sun.jvm.hotspot.debugger.linux.ppc64.*; import sun.jvm.hotspot.debugger.linux.sparc.*; @@ -39,8 +38,6 @@ class LinuxThreadContextFactory { return new LinuxX86ThreadContext(dbg); } else if (cpu.equals("amd64")) { return new LinuxAMD64ThreadContext(dbg); - } else if (cpu.equals("ia64")) { - return new LinuxIA64ThreadContext(dbg); } else if (cpu.equals("sparc")) { return new LinuxSPARCThreadContext(dbg); } else if (cpu.equals("ppc64")) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java index afe11938c42..fa7837cec6e 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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,10 +30,8 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.debugger.x86.*; -import sun.jvm.hotspot.debugger.ia64.*; import sun.jvm.hotspot.debugger.windbg.amd64.*; import sun.jvm.hotspot.debugger.windbg.x86.*; -import sun.jvm.hotspot.debugger.windbg.ia64.*; import sun.jvm.hotspot.debugger.win32.coff.*; import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.cdbg.basic.BasicDebugEvent; @@ -115,8 +113,6 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger threadFactory = new WindbgX86ThreadFactory(this); } else if (cpu.equals("amd64")) { threadFactory = new WindbgAMD64ThreadFactory(this); - } else if (cpu.equals("ia64")) { - threadFactory = new WindbgIA64ThreadFactory(this); } if (useCache) { @@ -231,11 +227,7 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger public CDebugger getCDebugger() throws DebuggerException { if (cdbg == null) { - // FIXME: CDebugger is not yet supported for IA64 because - // of native stack walking issues. - if (! getCPU().equals("ia64")) { - cdbg = new WindbgCDebugger(this); - } + cdbg = new WindbgCDebugger(this); } return cdbg; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64Thread.java deleted file mode 100644 index 591ad9cf5a9..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64Thread.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2003, 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.debugger.windbg.ia64; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.ia64.*; -import sun.jvm.hotspot.debugger.windbg.*; - -class WindbgIA64Thread implements ThreadProxy { - private WindbgDebugger debugger; - private long sysId; - private boolean gotID; - private long id; - - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ - WindbgIA64Thread(WindbgDebugger debugger, Address addr) { - this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; - } - - WindbgIA64Thread(WindbgDebugger debugger, long sysId) { - this.debugger = debugger; - this.sysId = sysId; - gotID = false; - } - - public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(getThreadID()); - WindbgIA64ThreadContext context = new WindbgIA64ThreadContext(debugger); - for (int i = 0; i < data.length; i++) { - context.setRegister(i, data[i]); - } - return context; - } - - public boolean canSetContext() throws DebuggerException { - return false; - } - - public void setContext(ThreadContext thrCtx) - throws IllegalThreadStateException, DebuggerException { - throw new DebuggerException("Unimplemented"); - } - - public boolean equals(Object obj) { - if ((obj == null) || !(obj instanceof WindbgIA64Thread)) { - return false; - } - - return (((WindbgIA64Thread) obj).getThreadID() == getThreadID()); - } - - public int hashCode() { - return (int) getThreadID(); - } - - public String toString() { - return Long.toString(getThreadID()); - } - - /** Retrieves the thread ID of this thread by examining the Thread - Information Block. */ - private long getThreadID() { - if (!gotID) { - id = debugger.getThreadIdFromSysId(sysId); - } - - return id; - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 1456c019951..4bcd98bd3da 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -474,20 +474,48 @@ public class InstanceKlass extends Klass { } // same as enum InnerClassAttributeOffset in VM code. - public static interface InnerClassAttributeOffset { + private static class InnerClassAttributeOffset { // from JVM spec. "InnerClasses" attribute - public static final int innerClassInnerClassInfoOffset = 0; - public static final int innerClassOuterClassInfoOffset = 1; - public static final int innerClassInnerNameOffset = 2; - public static final int innerClassAccessFlagsOffset = 3; - public static final int innerClassNextOffset = 4; - }; + public static int innerClassInnerClassInfoOffset; + public static int innerClassOuterClassInfoOffset; + public static int innerClassInnerNameOffset; + public static int innerClassAccessFlagsOffset; + public static int innerClassNextOffset; + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } - public static interface EnclosingMethodAttributeOffset { - public static final int enclosing_method_class_index_offset = 0; - public static final int enclosing_method_method_index_offset = 1; - public static final int enclosing_method_attribute_size = 2; - }; + private static synchronized void initialize(TypeDataBase db) { + innerClassInnerClassInfoOffset = db.lookupIntConstant( + "InstanceKlass::inner_class_inner_class_info_offset").intValue(); + innerClassOuterClassInfoOffset = db.lookupIntConstant( + "InstanceKlass::inner_class_outer_class_info_offset").intValue(); + innerClassInnerNameOffset = db.lookupIntConstant( + "InstanceKlass::inner_class_inner_name_offset").intValue(); + innerClassAccessFlagsOffset = db.lookupIntConstant( + "InstanceKlass::inner_class_access_flags_offset").intValue(); + innerClassNextOffset = db.lookupIntConstant( + "InstanceKlass::inner_class_next_offset").intValue(); + } + } + + private static class EnclosingMethodAttributeOffset { + public static int enclosingMethodAttributeSize; + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + private static synchronized void initialize(TypeDataBase db) { + enclosingMethodAttributeSize = db.lookupIntConstant("InstanceKlass::enclosing_method_attribute_size").intValue(); + } + } // refer to compute_modifier_flags in VM code. public long computeModifierFlags() { @@ -498,11 +526,11 @@ public class InstanceKlass extends Klass { if (length > 0) { if (Assert.ASSERTS_ENABLED) { Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || - length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size, + length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize, "just checking"); } for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { - if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { + if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) { break; } int ioff = innerClassList.at(i + @@ -547,11 +575,11 @@ public class InstanceKlass extends Klass { if (length > 0) { if (Assert.ASSERTS_ENABLED) { Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || - length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size, + length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize, "just checking"); } for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { - if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { + if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) { break; } int ioff = innerClassList.at(i + diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java index 241e5be3756..c0776dbad2b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -202,8 +202,7 @@ public class Oop { public boolean verify() { return true;} - // Package-private routine to speed up ObjectHeap.newOop - static Klass getKlassForOopHandle(OopHandle handle) { + public static Klass getKlassForOopHandle(OopHandle handle) { if (handle == null) { return null; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java index 4eab2fe6c91..1e3014655d0 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ public class java_lang_Class { // java.lang.Class fields static int klassOffset; + static int arrayKlassOffset; static IntField oopSizeField; static { @@ -56,6 +57,7 @@ public class java_lang_Class { // find them from InstanceKlass for java.lang.Class. Type jlc = db.lookupType("java_lang_Class"); klassOffset = (int) jlc.getCIntegerField("_klass_offset").getValue(); + arrayKlassOffset = (int) jlc.getCIntegerField("_array_klass_offset").getValue(); int oopSizeOffset = (int) jlc.getCIntegerField("_oop_size_offset").getValue(); oopSizeField = new IntField(new NamedFieldIdentifier("oop_size"), oopSizeOffset, true); } @@ -69,4 +71,23 @@ public class java_lang_Class { public static long getOopSize(Oop aClass) { return java_lang_Class.oopSizeField.getValue(aClass); } + + /** + * Returns the Java name for this Java mirror + */ + public static String asExternalName(Oop aClass) { + Klass k = java_lang_Class.asKlass(aClass); + if (k == null) { // primitive array + BasicType type = BasicType.T_VOID; + ArrayKlass ak = (ArrayKlass)Metadata.instantiateWrapperFor( + aClass.getHandle().getAddressAt(arrayKlassOffset)); + if (ak != null) { + type = BasicType.intToBasicType(ak.getElementType()); + } + return type.getName(); + } else { + return k.getName().asString(); + } + } + } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicType.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicType.java index 8331b5d34ca..7c25edc41d6 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicType.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicType.java @@ -24,113 +24,160 @@ package sun.jvm.hotspot.runtime; +import java.util.Observer; +import sun.jvm.hotspot.types.TypeDataBase; + + /** Encapsulates the BasicType enum in globalDefinitions.hpp in the VM. */ public class BasicType { - public static final int tBoolean = 4; - public static final int tChar = 5; - public static final int tFloat = 6; - public static final int tDouble = 7; - public static final int tByte = 8; - public static final int tShort = 9; - public static final int tInt = 10; - public static final int tLong = 11; - public static final int tObject = 12; - public static final int tArray = 13; - public static final int tVoid = 14; - public static final int tAddress = 15; - public static final int tNarrowOop = 16; - public static final int tMetadata = 17; - public static final int tNarrowKlass = 18; - public static final int tConflict = 19; - public static final int tIllegal = 99; + public static final BasicType T_BOOLEAN = new BasicType(); + public static final BasicType T_CHAR = new BasicType(); + public static final BasicType T_FLOAT = new BasicType(); + public static final BasicType T_DOUBLE = new BasicType(); + public static final BasicType T_BYTE = new BasicType(); + public static final BasicType T_SHORT = new BasicType(); + public static final BasicType T_INT = new BasicType(); + public static final BasicType T_LONG = new BasicType(); + public static final BasicType T_OBJECT = new BasicType(); + public static final BasicType T_ARRAY = new BasicType(); + public static final BasicType T_VOID = new BasicType(); + public static final BasicType T_ADDRESS = new BasicType(); + public static final BasicType T_NARROWOOP = new BasicType(); + public static final BasicType T_METADATA = new BasicType(); + public static final BasicType T_NARROWKLASS = new BasicType(); + public static final BasicType T_CONFLICT = new BasicType(); + public static final BasicType T_ILLEGAL = new BasicType(); - public static final BasicType T_BOOLEAN = new BasicType(tBoolean); - public static final BasicType T_CHAR = new BasicType(tChar); - public static final BasicType T_FLOAT = new BasicType(tFloat); - public static final BasicType T_DOUBLE = new BasicType(tDouble); - public static final BasicType T_BYTE = new BasicType(tByte); - public static final BasicType T_SHORT = new BasicType(tShort); - public static final BasicType T_INT = new BasicType(tInt); - public static final BasicType T_LONG = new BasicType(tLong); - public static final BasicType T_OBJECT = new BasicType(tObject); - public static final BasicType T_ARRAY = new BasicType(tArray); - public static final BasicType T_VOID = new BasicType(tVoid); - public static final BasicType T_ADDRESS = new BasicType(tAddress); - public static final BasicType T_NARROWOOP = new BasicType(tNarrowOop); - public static final BasicType T_METADATA = new BasicType(tMetadata); - public static final BasicType T_NARROWKLASS = new BasicType(tNarrowKlass); - public static final BasicType T_CONFLICT = new BasicType(tConflict); - public static final BasicType T_ILLEGAL = new BasicType(tIllegal); + static { + VM.registerVMInitializedObserver( + (o, d) -> initialize(VM.getVM().getTypeDataBase())); + } + + private static synchronized void initialize(TypeDataBase db) { + T_BOOLEAN.setType(db.lookupIntConstant("T_BOOLEAN").intValue()); + T_CHAR.setType(db.lookupIntConstant("T_CHAR").intValue()); + T_FLOAT.setType(db.lookupIntConstant("T_FLOAT").intValue()); + T_DOUBLE.setType(db.lookupIntConstant("T_DOUBLE").intValue()); + T_BYTE.setType(db.lookupIntConstant("T_BYTE").intValue()); + T_SHORT.setType(db.lookupIntConstant("T_SHORT").intValue()); + T_INT.setType(db.lookupIntConstant("T_INT").intValue()); + T_LONG.setType(db.lookupIntConstant("T_LONG").intValue()); + T_OBJECT.setType(db.lookupIntConstant("T_OBJECT").intValue()); + T_ARRAY.setType(db.lookupIntConstant("T_ARRAY").intValue()); + T_VOID.setType(db.lookupIntConstant("T_VOID").intValue()); + T_ADDRESS.setType(db.lookupIntConstant("T_ADDRESS").intValue()); + T_NARROWOOP.setType(db.lookupIntConstant("T_NARROWOOP").intValue()); + T_METADATA.setType(db.lookupIntConstant("T_METADATA").intValue()); + T_NARROWKLASS.setType(db.lookupIntConstant("T_NARROWKLASS").intValue()); + T_CONFLICT.setType(db.lookupIntConstant("T_CONFLICT").intValue()); + T_ILLEGAL.setType(db.lookupIntConstant("T_ILLEGAL").intValue()); + } public static int getTBoolean() { - return tBoolean; + return T_BOOLEAN.getType(); } public static int getTChar() { - return tChar; + return T_CHAR.getType(); } public static int getTFloat() { - return tFloat; + return T_FLOAT.getType(); } public static int getTDouble() { - return tDouble; + return T_DOUBLE.getType(); } public static int getTByte() { - return tByte; + return T_BYTE.getType(); } public static int getTShort() { - return tShort; + return T_SHORT.getType(); } public static int getTInt() { - return tInt; + return T_INT.getType(); } public static int getTLong() { - return tLong; + return T_LONG.getType(); } public static int getTObject() { - return tObject; + return T_OBJECT.getType(); } public static int getTArray() { - return tArray; + return T_ARRAY.getType(); } public static int getTVoid() { - return tVoid; + return T_VOID.getType(); } public static int getTAddress() { - return tAddress; + return T_ADDRESS.getType(); } public static int getTNarrowOop() { - return tNarrowOop; + return T_NARROWOOP.getType(); } public static int getTMetadata() { - return tMetadata; + return T_METADATA.getType(); } public static int getTNarrowKlass() { - return tNarrowKlass; + return T_NARROWKLASS.getType(); } /** For stack value type with conflicting contents */ public static int getTConflict() { - return tConflict; + return T_CONFLICT.getType(); } public static int getTIllegal() { - return tIllegal; + return T_ILLEGAL.getType(); + } + + public static BasicType intToBasicType(int i) { + if (i == T_BOOLEAN.getType()) { + return T_BOOLEAN; + } else if (i == T_CHAR.getType()) { + return T_CHAR; + } else if (i == T_FLOAT.getType()) { + return T_FLOAT; + } else if (i == T_DOUBLE.getType()) { + return T_DOUBLE; + } else if (i == T_BYTE.getType()) { + return T_BYTE; + } else if (i == T_SHORT.getType()) { + return T_SHORT; + } else if (i == T_INT.getType()) { + return T_INT; + } else if (i == T_LONG.getType()) { + return T_LONG; + } else if (i == T_OBJECT.getType()) { + return T_OBJECT; + } else if (i == T_ARRAY.getType()) { + return T_ARRAY; + } else if (i == T_VOID.getType()) { + return T_VOID; + } else if (i == T_ADDRESS.getType()) { + return T_ADDRESS; + } else if (i == T_NARROWOOP.getType()) { + return T_NARROWOOP; + } else if (i == T_METADATA.getType()) { + return T_METADATA; + } else if (i == T_NARROWKLASS.getType()) { + return T_NARROWKLASS; + } else { + return T_ILLEGAL; + } } public static BasicType charToBasicType(char c) { @@ -158,8 +205,49 @@ public class BasicType { return type; } + public String getName() { + if (type == T_BOOLEAN.getType()) { + return "boolean"; + } else if (type == T_CHAR.getType()) { + return "char"; + } else if (type == T_FLOAT.getType()) { + return "float"; + } else if (type == T_DOUBLE.getType()) { + return "double"; + } else if (type == T_BYTE.getType()) { + return "byte"; + } else if (type == T_SHORT.getType()) { + return "short"; + } else if (type == T_INT.getType()) { + return "int"; + } else if (type == T_LONG.getType()) { + return "long"; + } else if (type == T_OBJECT.getType()) { + return "object"; + } else if (type == T_ARRAY.getType()) { + return "array"; + } else if (type == T_VOID.getType()) { + return "void"; + } else if (type == T_ADDRESS.getType()) { + return "address"; + } else if (type == T_NARROWOOP.getType()) { + return "narrow oop"; + } else if (type == T_METADATA.getType()) { + return "metadata"; + } else if (type == T_NARROWKLASS.getType()) { + return "narrow klass"; + } else if (type == T_CONFLICT.getType()) { + return "conflict"; + } else { + return "ILLEGAL TYPE"; + } + } + //-- Internals only below this point - private BasicType(int type) { + private BasicType() { + } + + private void setType(int type) { this.type = type; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicTypeSize.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicTypeSize.java index 2a18795ab99..e09d6f5e1ce 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicTypeSize.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicTypeSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -24,22 +24,48 @@ package sun.jvm.hotspot.runtime; +import java.util.Observer; +import sun.jvm.hotspot.types.TypeDataBase; + + /** Encapsulates the BasicTypeSize enum in globalDefinitions.hpp in the VM. */ public class BasicTypeSize { - private static boolean initialized = false; - private static int tBooleanSize = 1; - private static int tCharSize = 1; - private static int tFloatSize = 1; - private static int tDoubleSize = 2; - private static int tByteSize = 1; - private static int tShortSize = 1; - private static int tIntSize = 1; - private static int tLongSize = 2; - private static int tObjectSize = 1; - private static int tArraySize = 1; - private static int tVoidSize = 0; + private static int tBooleanSize; + private static int tCharSize; + private static int tFloatSize; + private static int tDoubleSize; + private static int tByteSize; + private static int tShortSize; + private static int tIntSize; + private static int tLongSize; + private static int tObjectSize; + private static int tArraySize; + private static int tNarrowOopSize; + private static int tNarrowKlassSize; + private static int tVoidSize; + + static { + VM.registerVMInitializedObserver( + (o, d) -> initialize(VM.getVM().getTypeDataBase())); + } + + private static synchronized void initialize(TypeDataBase db) { + tBooleanSize = db.lookupIntConstant("T_BOOLEAN_size").intValue(); + tCharSize = db.lookupIntConstant("T_INT_size").intValue(); + tFloatSize = db.lookupIntConstant("T_FLOAT_size").intValue(); + tDoubleSize = db.lookupIntConstant("T_DOUBLE_size").intValue(); + tByteSize = db.lookupIntConstant("T_BYTE_size").intValue(); + tShortSize = db.lookupIntConstant("T_SHORT_size").intValue(); + tIntSize = db.lookupIntConstant("T_INT_size").intValue(); + tLongSize = db.lookupIntConstant("T_LONG_size").intValue(); + tObjectSize = db.lookupIntConstant("T_OBJECT_size").intValue(); + tArraySize = db.lookupIntConstant("T_ARRAY_size").intValue(); + tNarrowOopSize = db.lookupIntConstant("T_NARROWOOP_size").intValue(); + tNarrowKlassSize = db.lookupIntConstant("T_NARROWKLASS_size").intValue(); + tVoidSize = db.lookupIntConstant("T_VOID_size").intValue(); + } public static int getTBooleanSize() { return tBooleanSize; @@ -81,6 +107,14 @@ public class BasicTypeSize { return tArraySize; } + public static int getTNarrowOopSize() { + return tNarrowOopSize; + } + + public static int getTNarrowKlassSize() { + return tNarrowKlassSize; + } + public static int getTVoidSize() { return tVoidSize; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java index ba42e8da19f..a2d67b3fe3e 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -127,12 +127,12 @@ public class CompiledVFrame extends JavaVFrame { } /** Returns List */ - public List getMonitors() { + public List getMonitors() { List monitors = getScope().getMonitors(); if (monitors == null) { - return new ArrayList(); + return new ArrayList<>(); } - List result = new ArrayList(monitors.size()); + List result = new ArrayList<>(monitors.size()); for (int i = 0; i < monitors.size(); i++) { MonitorValue mv = (MonitorValue) monitors.get(i); ScopeValue ov = mv.owner(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java index 180de93a366..75750548ef5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -108,8 +108,8 @@ public class InterpretedVFrame extends JavaVFrame { } /** Returns List */ - public List getMonitors() { - List result = new ArrayList(5); + public List getMonitors() { + List result = new ArrayList<>(5); for (BasicObjectLock current = getFrame().interpreterFrameMonitorEnd(); current.address().lessThan(getFrame().interpreterFrameMonitorBegin().address()); current = getFrame().nextMonitorInInterpreterFrame(current)) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java index a45cbc3640c..5486d6c2bc3 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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,14 +28,19 @@ import java.io.*; import java.util.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.debugger.*; public abstract class JavaVFrame extends VFrame { + + private static final String ADDRESS_FORMAT = VM.getVM().isLP64() ? "0x%016x" + : "0x%08x"; + /** JVM state */ public abstract Method getMethod(); public abstract int getBCI(); public abstract StackValueCollection getLocals(); public abstract StackValueCollection getExpressions(); - public abstract List getMonitors(); // List + public abstract List getMonitors(); /** Test operation */ public boolean isJavaFrame() { return true; } @@ -49,9 +54,112 @@ public abstract class JavaVFrame extends VFrame { // FIXME: not yet implemented // public Address getPendingMonitor(int frameCount); + public void printLockedObjectClassName(PrintStream tty, + OopHandle hobj, String lockState) { + if (hobj.asLongValue() != 0L) { + tty.format("\t- %s <" + ADDRESS_FORMAT + "> ", + lockState, hobj.asLongValue()); + + Klass klass = Oop.getKlassForOopHandle(hobj); + String klassName = klass.getName().asString(); + tty.print("(a "); + if (klassName.equals("java/lang/Class")) { + Oop obj = VM.getVM().getObjectHeap().newOop(hobj); + klassName = java_lang_Class.asExternalName(obj); + tty.print("java.lang.Class for "); + } + tty.println(klassName.replace('/', '.') + ")"); + } + } + + private String identifyLockState(MonitorInfo monitor, String waitingState) { + Mark mark = new Mark(monitor.owner()); + if (mark.hasMonitor() && + ( // we have marked ourself as pending on this monitor + mark.monitor().equals(thread.getCurrentPendingMonitor()) || + // we are not the owner of this monitor + !mark.monitor().isEntered(thread) + )) { + return waitingState; + } + return "locked"; + } + /** Printing used during stack dumps */ - // FIXME: not yet implemented - // void print_lock_info(int frame_count); + public void printLockInfo(PrintStream tty, int frameCount) { + // If this is the first frame and it is java.lang.Object.wait(...) + // then print out the receiver. Locals are not always available, + // e.g., compiled native frames have no scope so there are no locals. + if (frameCount == 0) { + if (getMethod().getName().asString().equals("wait") && + getMethod().getMethodHolder().getName().asString().equals("java/lang/Object")) { + String waitState = "waiting on"; // assume we are waiting + // If earlier in the output we reported java.lang.Thread.State == + // "WAITING (on object monitor)" and now we report "waiting on", then + // we are still waiting for notification or timeout. Otherwise if + // we earlier reported java.lang.Thread.State == "BLOCKED (on object + // monitor)", then we are actually waiting to re-lock the monitor. + // At this level we can't distinguish the two cases to report + // "waited on" rather than "waiting on" for the second case. + StackValueCollection locs = getLocals(); + if (!locs.isEmpty()) { + StackValue sv = locs.get(0); + if (sv.getType() == BasicType.getTObject()) { + OopHandle o = sv.getObject(); + printLockedObjectClassName(tty, o, waitState); + } + } else { + tty.println("\t- " + waitState + " "); + } + } else if (thread.getCurrentParkBlocker() != null) { + Oop obj = thread.getCurrentParkBlocker(); + Klass k = obj.getKlass(); + tty.format("\t- parking to wait for <" + ADDRESS_FORMAT + "> (a %s)", + obj.getHandle().asLongValue(), k.getName().asString()); + tty.println(); + } + } + + // Print out all monitors that we have locked, or are trying to lock, + // including re-locking after being notified or timing out in a wait(). + List mons = getMonitors(); + if (!mons.isEmpty()) { + boolean foundFirstMonitor = false; + for (int index = mons.size() - 1; index >= 0; index--) { + MonitorInfo monitor = mons.get(index); + if (monitor.eliminated() && isCompiledFrame()) { // Eliminated in compiled code + if (monitor.ownerIsScalarReplaced()) { + Klass k = Oop.getKlassForOopHandle(monitor.ownerKlass()); + tty.println("\t- eliminated (a " + k.getName().asString() + ")"); + } else if (monitor.owner() != null) { + printLockedObjectClassName(tty, monitor.owner(), "eliminated"); + } + continue; + } + if (monitor.owner() != null) { + // the monitor is associated with an object, i.e., it is locked + String lockState = "locked"; + if (!foundFirstMonitor && frameCount == 0) { + // If this is the first frame and we haven't found an owned + // monitor before, then we need to see if we have completed + // the lock or if we are blocked trying to acquire it. Only + // an inflated monitor that is first on the monitor list in + // the first frame can block us on a monitor enter. + lockState = identifyLockState(monitor, "waiting to lock"); + } else if (frameCount != 0) { + // This is not the first frame so we either own this monitor + // or we owned the monitor before and called wait(). Because + // wait() could have been called on any monitor in a lower + // numbered frame on the stack, we have to check all the + // monitors on the list for this frame. + lockState = identifyLockState(monitor, "waiting to re-lock in wait()"); + } + printLockedObjectClassName(tty, monitor.owner(), lockState); + foundFirstMonitor = true; + } + } + } + } /** Printing operations */ @@ -73,22 +181,6 @@ public abstract class JavaVFrame extends VFrame { printStackValuesOn(tty, "locals", getLocals()); printStackValuesOn(tty, "expressions", getExpressions()); - - // List - // FIXME: not yet implemented - // List list = getMonitors(); - // if (list.isEmpty()) { - // return; - // } - // for (int index = 0; index < list.size(); index++) { - // MonitorInfo monitor = (MonitorInfo) list.get(index); - // tty.print("\t obj\t"); - // monitor.getOwner().printValueOn(tty); - // tty.println(); - // tty.print("\t "); - // monitor.lock().printOn(tty); - // tty.println(); - // } } public void printActivation(int index) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java index aee92a4f654..e5f72b0783c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java @@ -44,9 +44,7 @@ public class ObjectSynchronizer { Type type; try { type = db.lookupType("ObjectSynchronizer"); - AddressField blockListField; - blockListField = type.getAddressField("gBlockList"); - gBlockListAddr = blockListField.getValue(); + gBlockList = type.getAddressField("gBlockList").getValue(); blockSize = db.lookupIntConstant("ObjectSynchronizer::_BLOCKSIZE").intValue(); defaultCacheLineSize = db.lookupIntConstant("DEFAULT_CACHE_LINE_SIZE").intValue(); } catch (RuntimeException e) { } @@ -84,7 +82,7 @@ public class ObjectSynchronizer { } public static Iterator objectMonitorIterator() { - if (gBlockListAddr != null) { + if (gBlockList != null) { return new ObjectMonitorIterator(); } else { return null; @@ -97,7 +95,7 @@ public class ObjectSynchronizer { // and are not included by this Iterator. May add them later. ObjectMonitorIterator() { - blockAddr = gBlockListAddr; + blockAddr = gBlockList; index = blockSize - 1; block = new ObjectMonitor(blockAddr); } @@ -131,7 +129,7 @@ public class ObjectSynchronizer { private Address blockAddr; } - private static Address gBlockListAddr; + private static Address gBlockList; private static int blockSize; private static int defaultCacheLineSize; private static long objectMonitorTypeSize; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/PerfDataEntry.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/PerfDataEntry.java index 5d16b7026b5..a8da801532d 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/PerfDataEntry.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/PerfDataEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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 @@ -92,14 +92,29 @@ public class PerfDataEntry extends VMObject { return (flags() & 0x1) != 0; } - // NOTE: Keep this in sync with PerfData::Units enum in VM code - public interface PerfDataUnits { - public static final int U_None = 1; - public static final int U_Bytes = 2; - public static final int U_Ticks = 3; - public static final int U_Events = 4; - public static final int U_String = 5; - public static final int U_Hertz = 6; + private static class PerfDataUnits { + public static int U_None; + public static int U_Bytes; + public static int U_Ticks; + public static int U_Events; + public static int U_String; + public static int U_Hertz; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + private static synchronized void initialize(TypeDataBase db) { + U_None = db.lookupIntConstant("PerfData::U_None"); + U_Bytes = db.lookupIntConstant("PerfData::U_Bytes"); + U_Ticks = db.lookupIntConstant("PerfData::U_Ticks"); + U_Events = db.lookupIntConstant("PerfData::U_Events"); + U_String = db.lookupIntConstant("PerfData::U_String"); + U_Hertz = db.lookupIntConstant("PerfData::U_Hertz"); + } } // returns one of the constants in PerfDataUnits @@ -107,13 +122,6 @@ public class PerfDataEntry extends VMObject { return (int) dataUnitsField.getValue(addr); } - // NOTE: Keep this in sync with PerfData::Variability enum in VM code - public interface PerfDataVariability { - public static final int V_Constant = 1; - public static final int V_Monotonic = 2; - public static final int V_Variable = 3; - } - // returns one of the constants in PerfDataVariability public int dataVariability() { return (int) dataVariabilityField.getValue(addr); @@ -131,7 +139,7 @@ public class PerfDataEntry extends VMObject { public boolean booleanValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tBoolean, "not a boolean"); + dataType() == BasicType.getTBoolean(), "not a boolean"); } return addr.getJBooleanAt(dataOffset()); } @@ -139,7 +147,7 @@ public class PerfDataEntry extends VMObject { public char charValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tChar, "not a char"); + dataType() == BasicType.getTChar(), "not a char"); } return addr.getJCharAt(dataOffset()); } @@ -147,7 +155,7 @@ public class PerfDataEntry extends VMObject { public byte byteValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tByte, "not a byte"); + dataType() == BasicType.getTByte(), "not a byte"); } return addr.getJByteAt(dataOffset()); @@ -156,7 +164,7 @@ public class PerfDataEntry extends VMObject { public short shortValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tShort, "not a short"); + dataType() == BasicType.getTShort(), "not a short"); } return addr.getJShortAt(dataOffset()); } @@ -164,7 +172,7 @@ public class PerfDataEntry extends VMObject { public int intValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tInt, "not an int"); + dataType() == BasicType.getTInt(), "not an int"); } return addr.getJIntAt(dataOffset()); } @@ -172,7 +180,7 @@ public class PerfDataEntry extends VMObject { public long longValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tLong, "not a long"); + dataType() == BasicType.getTLong(), "not a long"); } return addr.getJLongAt(dataOffset()); } @@ -180,7 +188,7 @@ public class PerfDataEntry extends VMObject { public float floatValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tFloat, "not a float"); + dataType() == BasicType.getTFloat(), "not a float"); } return addr.getJFloatAt(dataOffset()); } @@ -188,7 +196,7 @@ public class PerfDataEntry extends VMObject { public double doubleValue() { if (Assert.ASSERTS_ENABLED) { Assert.that(vectorLength() == 0 && - dataType() == BasicType.tDouble, "not a double"); + dataType() == BasicType.getTDouble(), "not a double"); } return addr.getJDoubleAt(dataOffset()); } @@ -197,7 +205,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tBoolean, "not a boolean vector"); + dataType() == BasicType.getTBoolean(), "not a boolean vector"); } boolean[] res = new boolean[len]; final int off = dataOffset(); @@ -212,7 +220,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tChar, "not a char vector"); + dataType() == BasicType.getTChar(), "not a char vector"); } char[] res = new char[len]; final int off = dataOffset(); @@ -227,7 +235,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tByte, "not a byte vector"); + dataType() == BasicType.getTByte(), "not a byte vector"); } byte[] res = new byte[len]; final int off = dataOffset(); @@ -242,7 +250,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tShort, "not a short vector"); + dataType() == BasicType.getTShort(), "not a short vector"); } short[] res = new short[len]; final int off = dataOffset(); @@ -257,7 +265,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tInt, "not an int vector"); + dataType() == BasicType.getTInt(), "not an int vector"); } int[] res = new int[len]; final int off = dataOffset(); @@ -272,7 +280,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tLong, "not a long vector"); + dataType() == BasicType.getTLong(), "not a long vector"); } long[] res = new long[len]; final int off = dataOffset(); @@ -287,7 +295,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tFloat, "not a float vector"); + dataType() == BasicType.getTFloat(), "not a float vector"); } float[] res = new float[len]; final int off = dataOffset(); @@ -302,7 +310,7 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); if (Assert.ASSERTS_ENABLED) { Assert.that(len > 0 && - dataType() == BasicType.tDouble, "not a double vector"); + dataType() == BasicType.getTDouble(), "not a double vector"); } double[] res = new double[len]; final int off = dataOffset(); @@ -319,38 +327,27 @@ public class PerfDataEntry extends VMObject { int len = vectorLength(); String str = null; if (len == 0) { // scalar - switch (dataType) { - case BasicType.tBoolean: + if (dataType == BasicType.getTBoolean()) { str = Boolean.toString(booleanValue()); - break; - case BasicType.tChar: + } else if (dataType == BasicType.getTChar()) { str = "'" + Character.toString(charValue()) + "'"; - break; - case BasicType.tByte: + } else if (dataType == BasicType.getTByte()) { str = Byte.toString(byteValue()); - break; - case BasicType.tShort: + } else if (dataType == BasicType.getTShort()) { str = Short.toString(shortValue()); - break; - case BasicType.tInt: + } else if (dataType == BasicType.getTInt()) { str = Integer.toString(intValue()); - break; - case BasicType.tLong: + } else if (dataType == BasicType.getTLong()) { str = Long.toString(longValue()); - break; - case BasicType.tFloat: + } else if (dataType == BasicType.getTFloat()) { str = Float.toString(floatValue()); - break; - case BasicType.tDouble: + } else if (dataType == BasicType.getTDouble()) { str = Double.toString(doubleValue()); - break; - default: + } else { str = ""; - break; } } else { // vector - switch (dataType) { - case BasicType.tBoolean: { + if (dataType == BasicType.getTBoolean()) { boolean[] res = booleanArrayValue(); StringBuffer buf = new StringBuffer(); buf.append('['); @@ -360,26 +357,17 @@ public class PerfDataEntry extends VMObject { } buf.append(']'); str = buf.toString(); - break; - } - - case BasicType.tChar: { + } else if (dataType == BasicType.getTChar()) { // char[] is returned as a String str = new String(charArrayValue()); - break; - } - - case BasicType.tByte: { + } else if (dataType == BasicType.getTByte()) { // byte[] is returned as a String try { str = new String(byteArrayValue(), "US-ASCII"); } catch (java.io.UnsupportedEncodingException e) { str = "can't decode string : " + e.getMessage(); } - break; - } - - case BasicType.tShort: { + } else if (dataType == BasicType.getTShort()) { short[] res = shortArrayValue(); StringBuffer buf = new StringBuffer(); buf.append('['); @@ -389,10 +377,7 @@ public class PerfDataEntry extends VMObject { } buf.append(']'); str = buf.toString(); - break; - } - - case BasicType.tInt: { + } else if (dataType == BasicType.getTInt()) { int[] res = intArrayValue(); StringBuffer buf = new StringBuffer(); buf.append('['); @@ -402,10 +387,7 @@ public class PerfDataEntry extends VMObject { } buf.append(']'); str = buf.toString(); - break; - } - - case BasicType.tLong: { + } else if (dataType == BasicType.getTLong()) { long[] res = longArrayValue(); StringBuffer buf = new StringBuffer(); buf.append('['); @@ -415,10 +397,7 @@ public class PerfDataEntry extends VMObject { } buf.append(']'); str = buf.toString(); - break; - } - - case BasicType.tFloat: { + } else if (dataType == BasicType.getTFloat()) { float[] res = floatArrayValue(); StringBuffer buf = new StringBuffer(); buf.append('['); @@ -428,10 +407,7 @@ public class PerfDataEntry extends VMObject { } buf.append(']'); str = buf.toString(); - break; - } - - case BasicType.tDouble: { + } else if (dataType == BasicType.getTDouble()) { double[] res = doubleArrayValue(); StringBuffer buf = new StringBuffer(); buf.append('['); @@ -441,33 +417,22 @@ public class PerfDataEntry extends VMObject { } buf.append(']'); str = buf.toString(); - break; - } - - default: + } else { str = ""; - break; } } // add units - switch (dataUnits()) { - case PerfDataUnits.U_None: - break; - case PerfDataUnits.U_Bytes: + int dataUnitsValue = dataUnits(); + + if (dataUnitsValue == PerfDataUnits.U_Bytes) { str += " byte(s)"; - break; - case PerfDataUnits.U_Ticks: + } else if (dataUnitsValue == PerfDataUnits.U_Ticks) { str += " tick(s)"; - break; - case PerfDataUnits.U_Events: + } else if (dataUnitsValue == PerfDataUnits.U_Events) { str += " event(s)"; - break; - case PerfDataUnits.U_String: - break; - case PerfDataUnits.U_Hertz: + } else if (dataUnitsValue == PerfDataUnits.U_Hertz) { str += " Hz"; - break; } return str; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java index 2506d417371..f4d7827254c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,10 +117,7 @@ public class VFrame { return null; } Frame s = fr.realSender(tempMap); - // ia64 in 1.4.1 only has java frames and no entryFrame - // so "s" can be null here for the first frame. if (s == null) { - Assert.that(VM.getVM().getCPU().equals("ia64"), "Only ia64 should have null here"); return null; } if (s.isFirstFrame()) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java index 7774fb68df0..0072a5bf64b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java @@ -76,6 +76,8 @@ public class StackTrace extends Tool { if (cur.isJavaThread()) { cur.printThreadInfoOn(tty); try { + int count = 0; + for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { Method method = vf.getMethod(); tty.print(" - " + method.externalNameAndSignature() + @@ -109,6 +111,7 @@ public class StackTrace extends Tool { } tty.println(")"); + vf.printLockInfo(tty, count++); } } catch (Exception e) { tty.println("Error occurred during stack walking:"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/PackageNameFilter.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/PackageNameFilter.java index 1701c11b02d..e0312ff5a4d 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/PackageNameFilter.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/PackageNameFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,10 +50,14 @@ public class PackageNameFilter implements ClassFilter } public boolean canInclude(InstanceKlass kls) { - String klassName = kls.getName().asString().replace('/', '.'); + if (pkgList == null) { + // Dump everything + return true; + } final int len = pkgList.length; if (len == 0) return true; + String klassName = kls.getName().asString().replace('/', '.'); for (int i=0; i < len; i++) if (klassName.startsWith((String) pkgList[i] )) return true; return false; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java index d2d639214af..f37d15e696f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java @@ -1910,6 +1910,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants { buf.append(thread.getThreadState().toString()); buf.br(); buf.beginTag("pre"); + int count = 0; for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { Method method = vf.getMethod(); buf.append(" - "); @@ -1954,6 +1955,19 @@ public class HTMLGenerator implements /* imports */ ClassConstants { } buf.append(")"); buf.br(); + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(bytes); + try (printStream) { + vf.printLockInfo(printStream, count++); + for (String line : bytes.toString().split("\n")) { + if (genHTML) { + line = line.replace("<", "<").replace(">", ">"); + } + buf.append(line); + buf.br(); + } + } } buf.endTag("pre"); diff --git a/src/jdk.hotspot.agent/solaris/native/libsaproc/libproc.h b/src/jdk.hotspot.agent/solaris/native/libsaproc/libproc.h index a91f72a7e31..b926ad94102 100644 --- a/src/jdk.hotspot.agent/solaris/native/libsaproc/libproc.h +++ b/src/jdk.hotspot.agent/solaris/native/libsaproc/libproc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,14 +77,14 @@ extern int _libproc_debug; /* set non-zero to enable debugging fprintfs */ typedef uint32_t syscall_t; /* holds a syscall instruction */ #endif /* sparc */ -#if defined(__i386) || defined(__ia64) +#if defined(__i386) #define R_PC EIP #define R_SP UESP #define R_RVAL1 EAX /* register holding a function return value */ #define R_RVAL2 EDX /* 32 more bits for a 64-bit return value */ #define SYSCALL 0x9a /* syscall (lcall) instruction opcode */ typedef uchar_t syscall_t[7]; /* holds a syscall instruction */ -#endif /* __i386 || __ia64 */ +#endif /* __i386 */ #define R_RVAL R_RVAL1 /* simple function return value register */ diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index 04e0e22182d..089cb3f4b0e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -352,17 +352,18 @@ public class AMD64Assembler extends Assembler { */ private enum OpAssertion { ByteAssertion(CPU, CPU, BYTE), - IntegerAssertion(CPU, CPU, WORD, DWORD, QWORD), - No16BitAssertion(CPU, CPU, DWORD, QWORD), - No32BitAssertion(CPU, CPU, WORD, QWORD), - QwordOnlyAssertion(CPU, CPU, QWORD), - FloatingAssertion(XMM, XMM, SS, SD, PS, PD), - PackedFloatingAssertion(XMM, XMM, PS, PD), + ByteOrLargerAssertion(CPU, CPU, BYTE, WORD, DWORD, QWORD), + WordOrLargerAssertion(CPU, CPU, WORD, DWORD, QWORD), + DwordOrLargerAssertion(CPU, CPU, DWORD, QWORD), + WordOrDwordAssertion(CPU, CPU, WORD, QWORD), + QwordAssertion(CPU, CPU, QWORD), + FloatAssertion(XMM, XMM, SS, SD, PS, PD), + PackedFloatAssertion(XMM, XMM, PS, PD), SingleAssertion(XMM, XMM, SS), DoubleAssertion(XMM, XMM, SD), PackedDoubleAssertion(XMM, XMM, PD), - IntToFloatingAssertion(XMM, CPU, DWORD, QWORD), - FloatingToIntAssertion(CPU, XMM, DWORD, QWORD); + IntToFloatAssertion(XMM, CPU, DWORD, QWORD), + FloatToIntAssertion(CPU, XMM, DWORD, QWORD); private final RegisterCategory resultCategory; private final RegisterCategory inputCategory; @@ -772,25 +773,25 @@ public class AMD64Assembler extends Assembler { */ public static class AMD64RMOp extends AMD64RROp { // @formatter:off - public static final AMD64RMOp IMUL = new AMD64RMOp("IMUL", P_0F, 0xAF); + public static final AMD64RMOp IMUL = new AMD64RMOp("IMUL", P_0F, 0xAF, OpAssertion.ByteOrLargerAssertion); public static final AMD64RMOp BSF = new AMD64RMOp("BSF", P_0F, 0xBC); public static final AMD64RMOp BSR = new AMD64RMOp("BSR", P_0F, 0xBD); public static final AMD64RMOp POPCNT = new AMD64RMOp("POPCNT", 0xF3, P_0F, 0xB8, CPUFeature.POPCNT); public static final AMD64RMOp TZCNT = new AMD64RMOp("TZCNT", 0xF3, P_0F, 0xBC, CPUFeature.BMI1); public static final AMD64RMOp LZCNT = new AMD64RMOp("LZCNT", 0xF3, P_0F, 0xBD, CPUFeature.LZCNT); - public static final AMD64RMOp MOVZXB = new AMD64RMOp("MOVZXB", P_0F, 0xB6, false, true, OpAssertion.IntegerAssertion); - public static final AMD64RMOp MOVZX = new AMD64RMOp("MOVZX", P_0F, 0xB7, OpAssertion.No16BitAssertion); - public static final AMD64RMOp MOVSXB = new AMD64RMOp("MOVSXB", P_0F, 0xBE, false, true, OpAssertion.IntegerAssertion); - public static final AMD64RMOp MOVSX = new AMD64RMOp("MOVSX", P_0F, 0xBF, OpAssertion.No16BitAssertion); - public static final AMD64RMOp MOVSXD = new AMD64RMOp("MOVSXD", 0x63, OpAssertion.QwordOnlyAssertion); + public static final AMD64RMOp MOVZXB = new AMD64RMOp("MOVZXB", P_0F, 0xB6, false, true, OpAssertion.WordOrLargerAssertion); + public static final AMD64RMOp MOVZX = new AMD64RMOp("MOVZX", P_0F, 0xB7, OpAssertion.DwordOrLargerAssertion); + public static final AMD64RMOp MOVSXB = new AMD64RMOp("MOVSXB", P_0F, 0xBE, false, true, OpAssertion.WordOrLargerAssertion); + public static final AMD64RMOp MOVSX = new AMD64RMOp("MOVSX", P_0F, 0xBF, OpAssertion.DwordOrLargerAssertion); + public static final AMD64RMOp MOVSXD = new AMD64RMOp("MOVSXD", 0x63, OpAssertion.QwordAssertion); public static final AMD64RMOp MOVB = new AMD64RMOp("MOVB", 0x8A, OpAssertion.ByteAssertion); public static final AMD64RMOp MOV = new AMD64RMOp("MOV", 0x8B); // MOVD/MOVQ and MOVSS/MOVSD are the same opcode, just with different operand size prefix - public static final AMD64RMOp MOVD = new AMD64RMOp("MOVD", 0x66, P_0F, 0x6E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); - public static final AMD64RMOp MOVQ = new AMD64RMOp("MOVQ", 0x66, P_0F, 0x6E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); - public static final AMD64RMOp MOVSS = new AMD64RMOp("MOVSS", P_0F, 0x10, OpAssertion.FloatingAssertion, CPUFeature.SSE); - public static final AMD64RMOp MOVSD = new AMD64RMOp("MOVSD", P_0F, 0x10, OpAssertion.FloatingAssertion, CPUFeature.SSE); + public static final AMD64RMOp MOVD = new AMD64RMOp("MOVD", 0x66, P_0F, 0x6E, OpAssertion.IntToFloatAssertion, CPUFeature.SSE2); + public static final AMD64RMOp MOVQ = new AMD64RMOp("MOVQ", 0x66, P_0F, 0x6E, OpAssertion.IntToFloatAssertion, CPUFeature.SSE2); + public static final AMD64RMOp MOVSS = new AMD64RMOp("MOVSS", P_0F, 0x10, OpAssertion.FloatAssertion, CPUFeature.SSE); + public static final AMD64RMOp MOVSD = new AMD64RMOp("MOVSD", P_0F, 0x10, OpAssertion.FloatAssertion, CPUFeature.SSE); // TEST is documented as MR operation, but it's symmetric, and using it as RM operation is more convenient. public static final AMD64RMOp TESTB = new AMD64RMOp("TEST", 0x84, OpAssertion.ByteAssertion); @@ -822,7 +823,7 @@ public class AMD64Assembler extends Assembler { } protected AMD64RMOp(String opcode, int prefix1, int prefix2, int op, CPUFeature feature) { - this(opcode, prefix1, prefix2, op, OpAssertion.IntegerAssertion, feature); + this(opcode, prefix1, prefix2, op, OpAssertion.WordOrLargerAssertion, feature); } protected AMD64RMOp(String opcode, int prefix1, int prefix2, int op, OpAssertion assertion, CPUFeature feature) { @@ -1014,7 +1015,7 @@ public class AMD64Assembler extends Assembler { } protected AMD64RRMOp(String opcode, int prefix1, int prefix2, int op, CPUFeature feature) { - this(opcode, prefix1, prefix2, op, OpAssertion.IntegerAssertion, feature); + this(opcode, prefix1, prefix2, op, OpAssertion.WordOrLargerAssertion, feature); } protected AMD64RRMOp(String opcode, int prefix1, int prefix2, int op, OpAssertion assertion, CPUFeature feature) { @@ -1114,12 +1115,12 @@ public class AMD64Assembler extends Assembler { // MOVD and MOVQ are the same opcode, just with different operand size prefix // Note that as MR opcodes, they have reverse operand order, so the IntToFloatingAssertion must be used. - public static final AMD64MROp MOVD = new AMD64MROp("MOVD", 0x66, P_0F, 0x7E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); - public static final AMD64MROp MOVQ = new AMD64MROp("MOVQ", 0x66, P_0F, 0x7E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); + public static final AMD64MROp MOVD = new AMD64MROp("MOVD", 0x66, P_0F, 0x7E, OpAssertion.IntToFloatAssertion, CPUFeature.SSE2); + public static final AMD64MROp MOVQ = new AMD64MROp("MOVQ", 0x66, P_0F, 0x7E, OpAssertion.IntToFloatAssertion, CPUFeature.SSE2); // MOVSS and MOVSD are the same opcode, just with different operand size prefix - public static final AMD64MROp MOVSS = new AMD64MROp("MOVSS", P_0F, 0x11, OpAssertion.FloatingAssertion, CPUFeature.SSE); - public static final AMD64MROp MOVSD = new AMD64MROp("MOVSD", P_0F, 0x11, OpAssertion.FloatingAssertion, CPUFeature.SSE); + public static final AMD64MROp MOVSS = new AMD64MROp("MOVSS", P_0F, 0x11, OpAssertion.FloatAssertion, CPUFeature.SSE); + public static final AMD64MROp MOVSD = new AMD64MROp("MOVSD", P_0F, 0x11, OpAssertion.FloatAssertion, CPUFeature.SSE); // @formatter:on protected AMD64MROp(String opcode, int op) { @@ -1131,7 +1132,7 @@ public class AMD64Assembler extends Assembler { } protected AMD64MROp(String opcode, int prefix, int op) { - this(opcode, prefix, op, OpAssertion.IntegerAssertion); + this(opcode, prefix, op, OpAssertion.WordOrLargerAssertion); } protected AMD64MROp(String opcode, int prefix, int op, OpAssertion assertion) { @@ -1279,7 +1280,7 @@ public class AMD64Assembler extends Assembler { public static final AMD64MOp INC = new AMD64MOp("INC", 0xFF, 0); public static final AMD64MOp DEC = new AMD64MOp("DEC", 0xFF, 1); public static final AMD64MOp PUSH = new AMD64MOp("PUSH", 0xFF, 6); - public static final AMD64MOp POP = new AMD64MOp("POP", 0x8F, 0, OpAssertion.No32BitAssertion); + public static final AMD64MOp POP = new AMD64MOp("POP", 0x8F, 0, OpAssertion.WordOrDwordAssertion); // @formatter:on private final int ext; @@ -1289,7 +1290,7 @@ public class AMD64Assembler extends Assembler { } protected AMD64MOp(String opcode, int prefix, int op, int ext) { - this(opcode, prefix, op, ext, OpAssertion.IntegerAssertion); + this(opcode, prefix, op, ext, OpAssertion.WordOrLargerAssertion); } protected AMD64MOp(String opcode, int op, int ext, OpAssertion assertion) { @@ -1327,7 +1328,7 @@ public class AMD64Assembler extends Assembler { private final int ext; protected AMD64MIOp(String opcode, boolean immIsByte, int op, int ext) { - this(opcode, immIsByte, op, ext, OpAssertion.IntegerAssertion); + this(opcode, immIsByte, op, ext, OpAssertion.WordOrLargerAssertion); } protected AMD64MIOp(String opcode, boolean immIsByte, int op, int ext, OpAssertion assertion) { @@ -1369,7 +1370,7 @@ public class AMD64Assembler extends Assembler { // @formatter:on protected AMD64RMIOp(String opcode, boolean immIsByte, int op) { - this(opcode, immIsByte, 0, op, OpAssertion.IntegerAssertion); + this(opcode, immIsByte, 0, op, OpAssertion.WordOrLargerAssertion); } protected AMD64RMIOp(String opcode, boolean immIsByte, int prefix, int op, OpAssertion assertion) { @@ -1504,16 +1505,16 @@ public class AMD64Assembler extends Assembler { public static class SSEOp extends AMD64RMOp { // @formatter:off - public static final SSEOp CVTSI2SS = new SSEOp("CVTSI2SS", 0xF3, P_0F, 0x2A, OpAssertion.IntToFloatingAssertion); - public static final SSEOp CVTSI2SD = new SSEOp("CVTSI2SS", 0xF2, P_0F, 0x2A, OpAssertion.IntToFloatingAssertion); - public static final SSEOp CVTTSS2SI = new SSEOp("CVTTSS2SI", 0xF3, P_0F, 0x2C, OpAssertion.FloatingToIntAssertion); - public static final SSEOp CVTTSD2SI = new SSEOp("CVTTSD2SI", 0xF2, P_0F, 0x2C, OpAssertion.FloatingToIntAssertion); - public static final SSEOp UCOMIS = new SSEOp("UCOMIS", P_0F, 0x2E, OpAssertion.PackedFloatingAssertion); + public static final SSEOp CVTSI2SS = new SSEOp("CVTSI2SS", 0xF3, P_0F, 0x2A, OpAssertion.IntToFloatAssertion); + public static final SSEOp CVTSI2SD = new SSEOp("CVTSI2SS", 0xF2, P_0F, 0x2A, OpAssertion.IntToFloatAssertion); + public static final SSEOp CVTTSS2SI = new SSEOp("CVTTSS2SI", 0xF3, P_0F, 0x2C, OpAssertion.FloatToIntAssertion); + public static final SSEOp CVTTSD2SI = new SSEOp("CVTTSD2SI", 0xF2, P_0F, 0x2C, OpAssertion.FloatToIntAssertion); + public static final SSEOp UCOMIS = new SSEOp("UCOMIS", P_0F, 0x2E, OpAssertion.PackedFloatAssertion); public static final SSEOp SQRT = new SSEOp("SQRT", P_0F, 0x51); - public static final SSEOp AND = new SSEOp("AND", P_0F, 0x54, OpAssertion.PackedFloatingAssertion); - public static final SSEOp ANDN = new SSEOp("ANDN", P_0F, 0x55, OpAssertion.PackedFloatingAssertion); - public static final SSEOp OR = new SSEOp("OR", P_0F, 0x56, OpAssertion.PackedFloatingAssertion); - public static final SSEOp XOR = new SSEOp("XOR", P_0F, 0x57, OpAssertion.PackedFloatingAssertion); + public static final SSEOp AND = new SSEOp("AND", P_0F, 0x54, OpAssertion.PackedFloatAssertion); + public static final SSEOp ANDN = new SSEOp("ANDN", P_0F, 0x55, OpAssertion.PackedFloatAssertion); + public static final SSEOp OR = new SSEOp("OR", P_0F, 0x56, OpAssertion.PackedFloatAssertion); + public static final SSEOp XOR = new SSEOp("XOR", P_0F, 0x57, OpAssertion.PackedFloatAssertion); public static final SSEOp ADD = new SSEOp("ADD", P_0F, 0x58); public static final SSEOp MUL = new SSEOp("MUL", P_0F, 0x59); public static final SSEOp CVTSS2SD = new SSEOp("CVTSS2SD", P_0F, 0x5A, OpAssertion.SingleAssertion); @@ -1525,7 +1526,7 @@ public class AMD64Assembler extends Assembler { // @formatter:on protected SSEOp(String opcode, int prefix, int op) { - this(opcode, prefix, op, OpAssertion.FloatingAssertion); + this(opcode, prefix, op, OpAssertion.FloatAssertion); } protected SSEOp(String opcode, int prefix, int op, OpAssertion assertion) { @@ -1539,10 +1540,10 @@ public class AMD64Assembler extends Assembler { public static class AVXOp extends AMD64RRMOp { // @formatter:off - public static final AVXOp AND = new AVXOp("AND", P_0F, 0x54, OpAssertion.PackedFloatingAssertion); - public static final AVXOp ANDN = new AVXOp("ANDN", P_0F, 0x55, OpAssertion.PackedFloatingAssertion); - public static final AVXOp OR = new AVXOp("OR", P_0F, 0x56, OpAssertion.PackedFloatingAssertion); - public static final AVXOp XOR = new AVXOp("XOR", P_0F, 0x57, OpAssertion.PackedFloatingAssertion); + public static final AVXOp AND = new AVXOp("AND", P_0F, 0x54, OpAssertion.PackedFloatAssertion); + public static final AVXOp ANDN = new AVXOp("ANDN", P_0F, 0x55, OpAssertion.PackedFloatAssertion); + public static final AVXOp OR = new AVXOp("OR", P_0F, 0x56, OpAssertion.PackedFloatAssertion); + public static final AVXOp XOR = new AVXOp("XOR", P_0F, 0x57, OpAssertion.PackedFloatAssertion); public static final AVXOp ADD = new AVXOp("ADD", P_0F, 0x58); public static final AVXOp MUL = new AVXOp("MUL", P_0F, 0x59); public static final AVXOp SUB = new AVXOp("SUB", P_0F, 0x5C); @@ -1552,7 +1553,7 @@ public class AMD64Assembler extends Assembler { // @formatter:on protected AVXOp(String opcode, int prefix, int op) { - this(opcode, prefix, op, OpAssertion.FloatingAssertion); + this(opcode, prefix, op, OpAssertion.FloatAssertion); } protected AVXOp(String opcode, int prefix, int op, OpAssertion assertion) { @@ -1595,10 +1596,10 @@ public class AMD64Assembler extends Assembler { byteMrOp = new AMD64MROp(opcode, 0, baseOp, OpAssertion.ByteAssertion); byteRmOp = new AMD64RMOp(opcode, 0, baseOp | 0x02, OpAssertion.ByteAssertion); - immOp = new AMD64MIOp(opcode, false, 0, 0x81, code, OpAssertion.IntegerAssertion); - immSxOp = new AMD64MIOp(opcode, true, 0, 0x83, code, OpAssertion.IntegerAssertion); - mrOp = new AMD64MROp(opcode, 0, baseOp | 0x01, OpAssertion.IntegerAssertion); - rmOp = new AMD64RMOp(opcode, 0, baseOp | 0x03, OpAssertion.IntegerAssertion); + immOp = new AMD64MIOp(opcode, false, 0, 0x81, code, OpAssertion.WordOrLargerAssertion); + immSxOp = new AMD64MIOp(opcode, true, 0, 0x83, code, OpAssertion.WordOrLargerAssertion); + mrOp = new AMD64MROp(opcode, 0, baseOp | 0x01, OpAssertion.WordOrLargerAssertion); + rmOp = new AMD64RMOp(opcode, 0, baseOp | 0x03, OpAssertion.WordOrLargerAssertion); } public AMD64MIOp getMIOpcode(OperandSize size, boolean sx) { @@ -1647,9 +1648,9 @@ public class AMD64Assembler extends Assembler { public final AMD64MIOp miOp; private AMD64Shift(String opcode, int code) { - m1Op = new AMD64MOp(opcode, 0, 0xD1, code, OpAssertion.IntegerAssertion); - mcOp = new AMD64MOp(opcode, 0, 0xD3, code, OpAssertion.IntegerAssertion); - miOp = new AMD64MIOp(opcode, true, 0, 0xC1, code, OpAssertion.IntegerAssertion); + m1Op = new AMD64MOp(opcode, 0, 0xD1, code, OpAssertion.WordOrLargerAssertion); + mcOp = new AMD64MOp(opcode, 0, 0xD3, code, OpAssertion.WordOrLargerAssertion); + miOp = new AMD64MIOp(opcode, true, 0, 0xC1, code, OpAssertion.WordOrLargerAssertion); } } @@ -1967,6 +1968,12 @@ public class AMD64Assembler extends Assembler { } } + public final void lead(Register dst, AMD64Address src) { + prefix(src, dst); + emitByte(0x8D); + emitOperandHelper(dst, src, 0); + } + public final void leaq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x8D); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java index f584d35d65a..95abe6f0e70 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java @@ -24,8 +24,6 @@ package org.graalvm.compiler.core.aarch64; -import jdk.vm.ci.aarch64.AArch64Kind; -import jdk.vm.ci.meta.JavaConstant; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.NumUtil; @@ -34,9 +32,11 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; -import org.graalvm.compiler.nodes.memory.address.RawAddressNode; import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase; +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.meta.JavaConstant; + public class AArch64AddressLoweringByUse extends AddressLoweringByUsePhase.AddressLoweringByUse { private AArch64LIRKindTool kindtool; @@ -46,9 +46,7 @@ public class AArch64AddressLoweringByUse extends AddressLoweringByUsePhase.Addre @Override public AddressNode lower(ValueNode use, Stamp stamp, AddressNode address) { - if (address instanceof RawAddressNode) { - return doLower(stamp, address.getBase(), null); - } else if (address instanceof OffsetAddressNode) { + if (address instanceof OffsetAddressNode) { OffsetAddressNode offsetAddress = (OffsetAddressNode) address; return doLower(stamp, offsetAddress.getBase(), offsetAddress.getOffset()); } else { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java index 3fddb853424..2737f18b574 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -88,7 +89,7 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { } } - LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference); + LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp(NodeView.DEFAULT)), baseReference, indexReference); gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, (int) displacement, scaleFactor, addressingMode)); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java index b99cd62bdad..3e98252c3e1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.memory.Access; import jdk.vm.ci.aarch64.AArch64Kind; @@ -45,7 +46,7 @@ public class AArch64NodeMatchRules extends NodeMatchRules { } protected AArch64Kind getMemoryKind(Access access) { - return (AArch64Kind) gen.getLIRKind(access.asNode().stamp()).getPlatformKind(); + return (AArch64Kind) gen.getLIRKind(access.asNode().stamp(NodeView.DEFAULT)).getPlatformKind(); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java index c95707da994..e3fb54825b0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java @@ -44,7 +44,7 @@ public class AMD64AllocatorTest extends AllocatorTest { @Test public void test1() { - testAllocation("test1snippet", 3, 1, 0); + testAllocation("test1snippet", 3, 0, 0); } public static long test1snippet(long x) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java index 63e535bc853..595e7174ed2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java @@ -25,24 +25,23 @@ package org.graalvm.compiler.core.amd64; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.PrimitiveStamp; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.LeftShiftNode; import org.graalvm.compiler.nodes.calc.NegateNode; -import org.graalvm.compiler.nodes.calc.ZeroExtendNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; import jdk.vm.ci.meta.JavaConstant; public class AMD64AddressLowering extends AddressLowering { - @Override - public AddressNode lower(ValueNode address) { - return lower(address, null); - } + private static final int ADDRESS_BITS = 64; @Override public AddressNode lower(ValueNode base, ValueNode offset) { @@ -54,9 +53,15 @@ public class AMD64AddressLowering extends AddressLowering { changed = improve(graph, base.getDebug(), ret, false, false); } while (changed); + assert checkAddressBitWidth(ret.getBase()); + assert checkAddressBitWidth(ret.getIndex()); return graph.unique(ret); } + private static boolean checkAddressBitWidth(ValueNode value) { + return value == null || value.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp || IntegerStamp.getBits(value.stamp(NodeView.DEFAULT)) == ADDRESS_BITS; + } + /** * Tries to optimize addresses so that they match the AMD64-specific addressing mode better * (base + index * scale + displacement). @@ -148,7 +153,7 @@ public class AMD64AddressLowering extends AddressLowering { if (base == ret.getBase()) { ret.setBase(originalBase); } else if (ret.getBase() != null) { - ret.setBase(graph.maybeAddOrUnique(NegateNode.create(ret.getBase()))); + ret.setBase(graph.maybeAddOrUnique(NegateNode.create(ret.getBase(), NodeView.DEFAULT))); } } @@ -156,7 +161,7 @@ public class AMD64AddressLowering extends AddressLowering { if (index == ret.getIndex()) { ret.setIndex(originalIndex); } else if (ret.getIndex() != null) { - ret.setIndex(graph.maybeAddOrUnique(NegateNode.create(ret.getIndex()))); + ret.setIndex(graph.maybeAddOrUnique(NegateNode.create(ret.getIndex(), NodeView.DEFAULT))); } } return improved; @@ -168,12 +173,12 @@ public class AMD64AddressLowering extends AddressLowering { private static ValueNode considerNegation(StructuredGraph graph, ValueNode value, boolean negate) { if (negate && value != null) { - return graph.maybeAddOrUnique(NegateNode.create(value)); + return graph.maybeAddOrUnique(NegateNode.create(value, NodeView.DEFAULT)); } return value; } - private ValueNode improveInput(AMD64AddressNode address, ValueNode node, int shift, boolean negateExtractedDisplacement) { + private static ValueNode improveInput(AMD64AddressNode address, ValueNode node, int shift, boolean negateExtractedDisplacement) { if (node == null) { return null; } @@ -182,30 +187,26 @@ public class AMD64AddressLowering extends AddressLowering { if (c != null) { return improveConstDisp(address, node, c, null, shift, negateExtractedDisplacement); } else { - if (node.stamp() instanceof IntegerStamp) { - if (node instanceof ZeroExtendNode && (((ZeroExtendNode) node).getInputBits() == 32)) { - /* - * we can't just swallow all zero-extends as we might encounter something like - * the following: ZeroExtend(Add(negativeValue, positiveValue)). - * - * if we swallow the zero-extend in this case and subsequently optimize the add, - * we might end up with a negative value that has less than 64 bits in base or - * index. such a value would require sign extension instead of zero-extension - * but the backend can only do zero-extension. if we ever want to optimize that - * further, we would also need to be careful about over-/underflows. - * - * furthermore, we also can't swallow zero-extends with less than 32 bits as - * most of these values are immediately sign-extended to 32 bit by the backend - * (therefore, the subsequent implicit zero-extension to 64 bit won't do what we - * expect). - */ - ValueNode value = ((ZeroExtendNode) node).getValue(); - if (!mightBeOptimized(value)) { - // if the value is not optimized further by the address lowering, then we - // can safely rely on the backend doing the implicitly zero-extension. - return value; - } - } + if (node.stamp(NodeView.DEFAULT) instanceof IntegerStamp) { + assert PrimitiveStamp.getBits(node.stamp(NodeView.DEFAULT)) == ADDRESS_BITS; + + /* + * we can't swallow zero-extends because of multiple reasons: + * + * a) we might encounter something like the following: ZeroExtend(Add(negativeValue, + * positiveValue)). if we swallow the zero-extend in this case and subsequently + * optimize the add, we might end up with a negative value that has less than 64 + * bits in base or index. such a value would require sign extension instead of + * zero-extension but the backend can only do (implicit) zero-extension by using a + * larger register (e.g., rax instead of eax). + * + * b) our backend does not guarantee that the upper half of a 64-bit register equals + * 0 if a 32-bit value is stored in there. + * + * c) we also can't swallow zero-extends with less than 32 bits as most of these + * values are immediately sign-extended to 32 bit by the backend (therefore, the + * subsequent implicit zero-extension to 64 bit won't do what we expect). + */ if (node instanceof AddNode) { AddNode add = (AddNode) node; @@ -221,13 +222,6 @@ public class AMD64AddressLowering extends AddressLowering { return node; } - /** - * This method returns true for all nodes that might be optimized by the address lowering. - */ - protected boolean mightBeOptimized(ValueNode value) { - return value instanceof AddNode || value instanceof LeftShiftNode || value instanceof NegateNode || value instanceof ZeroExtendNode; - } - private static ValueNode improveConstDisp(AMD64AddressNode address, ValueNode original, JavaConstant c, ValueNode other, int shift, boolean negateExtractedDisplacement) { if (c.getJavaKind().isNumericInteger()) { long delta = c.asLong() << shift; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java index 90a8258d41c..bd27ef756d3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; @@ -113,7 +114,7 @@ public class AMD64AddressNode extends AddressNode implements Simplifiable, LIRLo } } - LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference); + LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp(NodeView.DEFAULT)), baseReference, indexReference); gen.setResult(this, new AMD64AddressValue(kind, baseValue, indexValue, scale, displacement)); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index 11e770b6e50..5b442b1e3bf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -99,8 +99,9 @@ import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.amd64.AMD64Binary; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer; import org.graalvm.compiler.lir.amd64.AMD64ClearRegisterOp; -import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp; import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp; +import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp; +import org.graalvm.compiler.lir.amd64.AMD64Move; import org.graalvm.compiler.lir.amd64.AMD64MulDivOp; import org.graalvm.compiler.lir.amd64.AMD64ShiftOp; import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp; @@ -287,14 +288,33 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen return ((AMD64Kind) kind).isInteger(); } + private Variable emitBaseOffsetLea(LIRKind resultKind, Value base, int offset, OperandSize size) { + Variable result = getLIRGen().newVariable(resultKind); + AMD64AddressValue address = new AMD64AddressValue(resultKind, getLIRGen().asAllocatable(base), offset); + getLIRGen().append(new AMD64Move.LeaOp(result, address, size)); + return result; + } + @Override public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) { TargetDescription target = getLIRGen().target(); boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX); switch ((AMD64Kind) a.getPlatformKind()) { case DWORD: + if (isJavaConstant(b) && !setFlags) { + long displacement = asJavaConstant(b).asLong(); + if (NumUtil.isInt(displacement) && displacement != 1 && displacement != -1) { + return emitBaseOffsetLea(resultKind, a, (int) displacement, OperandSize.DWORD); + } + } return emitBinary(resultKind, ADD, DWORD, true, a, b, setFlags); case QWORD: + if (isJavaConstant(b) && !setFlags) { + long displacement = asJavaConstant(b).asLong(); + if (NumUtil.isInt(displacement) && displacement != 1 && displacement != -1) { + return emitBaseOffsetLea(resultKind, a, (int) displacement, OperandSize.QWORD); + } + } return emitBinary(resultKind, ADD, QWORD, true, a, b, setFlags); case SINGLE: if (isAvx) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java index 2e07cd3a23c..c72bf39b999 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java @@ -28,6 +28,7 @@ import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; +import org.graalvm.compiler.asm.amd64.AMD64Assembler; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.DataPointerConstant; import org.graalvm.compiler.debug.GraalError; @@ -85,7 +86,7 @@ public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase { @Override public AMD64LIRInstruction createMove(AllocatableValue dst, Value src) { if (src instanceof AMD64AddressValue) { - return new LeaOp(dst, (AMD64AddressValue) src); + return new LeaOp(dst, (AMD64AddressValue) src, AMD64Assembler.OperandSize.QWORD); } else if (isConstantValue(src)) { return createLoad(dst, asConstant(src)); } else if (isRegister(src) || isStackSlotValue(dst)) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java index 760f599d08c..7d6a4c7840f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java @@ -60,6 +60,7 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; @@ -478,7 +479,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Write object Narrow=narrow)") public ComplexMatchResult writeNarrow(WriteNode root, NarrowNode narrow) { return builder -> { - LIRKind writeKind = getLIRGeneratorTool().getLIRKind(root.value().stamp()); + LIRKind writeKind = getLIRGeneratorTool().getLIRKind(root.value().stamp(NodeView.DEFAULT)); getArithmeticLIRGenerator().emitStore(writeKind, operand(root.getAddress()), operand(narrow.getValue()), state(root)); return null; }; @@ -504,10 +505,10 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @Override public Value evaluate(NodeLIRBuilder builder) { AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); - LIRKind addressKind = LIRKind.combineDerived(getLIRGeneratorTool().getLIRKind(root.asNode().stamp()), + LIRKind addressKind = LIRKind.combineDerived(getLIRGeneratorTool().getLIRKind(root.asNode().stamp(NodeView.DEFAULT)), address.getBase(), address.getIndex()); AMD64AddressValue newAddress = address.withKind(addressKind); - LIRKind readKind = getLIRGeneratorTool().getLIRKind(root.stamp()); + LIRKind readKind = getLIRGeneratorTool().getLIRKind(root.stamp(NodeView.DEFAULT)); return getArithmeticLIRGenerator().emitZeroExtendMemory((AMD64Kind) readKind.getPlatformKind(), root.getResultBits(), newAddress, getState(access)); } @@ -517,7 +518,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(SignExtend (Narrow=narrow Read=access))") @MatchRule("(SignExtend (Narrow=narrow FloatingRead=access))") public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode narrow, LIRLowerableAccess access) { - LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp()); + LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp(NodeView.DEFAULT)); return emitSignExtendMemory(access, narrow.getResultBits(), root.getResultBits(), kind); } @@ -554,7 +555,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Reinterpret FloatingRead=access)") public ComplexMatchResult reinterpret(ReinterpretNode root, LIRLowerableAccess access) { return builder -> { - LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp()); + LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp(NodeView.DEFAULT)); return emitReinterpretMemory(kind, access); }; @@ -563,7 +564,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Write object Reinterpret=reinterpret)") public ComplexMatchResult writeReinterpret(WriteNode root, ReinterpretNode reinterpret) { return builder -> { - LIRKind kind = getLIRGeneratorTool().getLIRKind(reinterpret.getValue().stamp()); + LIRKind kind = getLIRGeneratorTool().getLIRKind(reinterpret.getValue().stamp(NodeView.DEFAULT)); AllocatableValue value = getLIRGeneratorTool().asAllocatable(operand(reinterpret.getValue())); AMD64AddressValue address = (AMD64AddressValue) operand(root.getAddress()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java index 2d94012cf75..d726673a6cd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java @@ -251,22 +251,34 @@ public class StampFactory { } public static Stamp[] createParameterStamps(Assumptions assumptions, ResolvedJavaMethod method) { - Signature sig = method.getSignature(); - Stamp[] result = new Stamp[sig.getParameterCount(!method.isStatic())]; - int index = 0; + return createParameterStamps(assumptions, method, false); + } - if (!method.isStatic()) { - result[index++] = StampFactory.objectNonNull(TypeReference.create(assumptions, method.getDeclaringClass())); + public static Stamp[] createParameterStamps(Assumptions assumptions, ResolvedJavaMethod method, boolean trustInterfaceTypes) { + Signature signature = method.getSignature(); + Stamp[] result = new Stamp[signature.getParameterCount(method.hasReceiver())]; + + int index = 0; + ResolvedJavaType accessingClass = method.getDeclaringClass(); + if (method.hasReceiver()) { + if (trustInterfaceTypes) { + result[index++] = StampFactory.objectNonNull(TypeReference.createTrusted(assumptions, accessingClass)); + } else { + result[index++] = StampFactory.objectNonNull(TypeReference.create(assumptions, accessingClass)); + } } - int max = sig.getParameterCount(false); - ResolvedJavaType accessingClass = method.getDeclaringClass(); - for (int i = 0; i < max; i++) { - JavaType type = sig.getParameterType(i, accessingClass); + for (int i = 0; i < signature.getParameterCount(false); i++) { + JavaType type = signature.getParameterType(i, accessingClass); JavaKind kind = type.getJavaKind(); + Stamp stamp; if (kind == JavaKind.Object && type instanceof ResolvedJavaType) { - stamp = StampFactory.object(TypeReference.create(assumptions, (ResolvedJavaType) type)); + if (trustInterfaceTypes) { + stamp = StampFactory.object(TypeReference.createTrusted(assumptions, (ResolvedJavaType) type)); + } else { + stamp = StampFactory.object(TypeReference.create(assumptions, (ResolvedJavaType) type)); + } } else { stamp = StampFactory.forKind(kind); } @@ -284,16 +296,28 @@ public class StampFactory { if (returnType.getJavaKind() == JavaKind.Object && returnType instanceof ResolvedJavaType) { ResolvedJavaType resolvedJavaType = (ResolvedJavaType) returnType; TypeReference reference = TypeReference.create(assumptions, resolvedJavaType); - if (resolvedJavaType.isInterface()) { - ResolvedJavaType implementor = resolvedJavaType.getSingleImplementor(); - if (implementor != null && !resolvedJavaType.equals(implementor)) { - TypeReference uncheckedType = TypeReference.createTrusted(assumptions, implementor); - return StampPair.create(StampFactory.object(reference, nonNull), StampFactory.object(uncheckedType, nonNull)); + ResolvedJavaType elementalType = resolvedJavaType.getElementalType(); + if (elementalType.isInterface()) { + assert reference == null || !reference.getType().equals(resolvedJavaType); + TypeReference uncheckedType; + ResolvedJavaType elementalImplementor = elementalType.getSingleImplementor(); + if (elementalImplementor != null && !elementalType.equals(elementalImplementor)) { + ResolvedJavaType implementor = elementalImplementor; + ResolvedJavaType t = resolvedJavaType; + while (t.isArray()) { + implementor = implementor.getArrayClass(); + t = t.getComponentType(); + } + uncheckedType = TypeReference.createTrusted(assumptions, implementor); + } else { + uncheckedType = TypeReference.createTrusted(assumptions, resolvedJavaType); } + return StampPair.create(StampFactory.object(reference, nonNull), StampFactory.object(uncheckedType, nonNull)); } return StampPair.createSingle(StampFactory.object(reference, nonNull)); } else { return StampPair.createSingle(StampFactory.forKind(returnType.getJavaKind())); } } + } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCAddressLowering.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCAddressLowering.java index 14725bf4982..13edb612d34 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCAddressLowering.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCAddressLowering.java @@ -33,11 +33,6 @@ import jdk.vm.ci.meta.JavaConstant; public class SPARCAddressLowering extends AddressLowering { - @Override - public AddressNode lower(ValueNode address) { - return lower(address, 0); - } - @Override public AddressNode lower(ValueNode base, ValueNode offset) { JavaConstant immBase = asImmediate(base); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java index abdef18c51e..1dee79bd5a4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.sparc.SPARCImmediateAddressValue; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -59,7 +60,7 @@ public class SPARCImmediateAddressNode extends AddressNode implements LIRLowerab AllocatableValue baseValue = tool.asAllocatable(gen.operand(base)); - LIRKind kind = tool.getLIRKind(stamp()); + LIRKind kind = tool.getLIRKind(stamp(NodeView.DEFAULT)); AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); if (baseReference != null) { kind = kind.makeDerivedReference(baseReference); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java index 3fee3e82ea1..456f17aa215 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.sparc.SPARCIndexedAddressValue; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -61,7 +62,7 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); AllocatableValue indexReference = LIRKind.derivedBaseFromValue(indexValue); - LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference); + LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp(NodeView.DEFAULT)), baseReference, indexReference); gen.setResult(this, new SPARCIndexedAddressValue(kind, baseValue, indexValue)); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIntegerCompareCanonicalizationPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIntegerCompareCanonicalizationPhase.java index 9f0cd9f3cdc..7c69a738408 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIntegerCompareCanonicalizationPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIntegerCompareCanonicalizationPhase.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; @@ -59,7 +60,7 @@ public class SPARCIntegerCompareCanonicalizationPhase extends Phase { } private static void min32(CompareNode enode, ValueNode v) { - Stamp s = v.stamp(); + Stamp s = v.stamp(NodeView.DEFAULT); if (s instanceof IntegerStamp) { int bits = ((IntegerStamp) s).getBits(); if (bits != 32 && bits != 64) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java index 8c1e5733a9d..877e98aae84 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.test; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; +import org.graalvm.compiler.nodes.NodeView; import org.junit.Test; import org.graalvm.compiler.api.directives.GraalDirectives; @@ -223,7 +224,7 @@ public class CountedLoopTest extends GraalCompilerTest { @Input private ValueNode iv; protected IVPropertyNode(IVProperty property, ValueNode iv) { - super(TYPE, iv.stamp().unrestricted()); + super(TYPE, iv.stamp(NodeView.DEFAULT).unrestricted()); this.property = property; this.iv = iv; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java index 51fdf9426d3..a364aae2f8f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java @@ -166,7 +166,8 @@ public class NodePropertiesTest extends GraalCompilerTest { ImprovementSavingCanonicalizer c2 = new ImprovementSavingCanonicalizer(); StructuredGraph g2 = parseForCompile(getResolvedJavaMethod("test2Snippet")); new CanonicalizerPhase(c2).apply(g2, htc); - Assert.assertTrue(c1.savedCycles > c2.savedCycles); + Assert.assertEquals(0, c1.savedCycles); + Assert.assertEquals(0, c2.savedCycles); } private static void prepareGraphForLoopFrequencies(StructuredGraph g, HighTierContext htc) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UncheckedInterfaceProviderTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UncheckedInterfaceProviderTest.java new file mode 100644 index 00000000000..bcb0fddc0ed --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UncheckedInterfaceProviderTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2017, 2017, 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.graalvm.compiler.core.test; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; + +import jdk.vm.ci.meta.ResolvedJavaType; +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.debug.BlackholeNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider; +import org.graalvm.compiler.nodes.type.StampTool; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class UncheckedInterfaceProviderTest extends GraalCompilerTest { + private Runnable interfaceField; + private Runnable[] interfaceArrayField; + + public void snippet(Runnable interfaceParameter, Runnable[] interfaceArrayParameter) { + GraalDirectives.blackhole(interfaceParameter); + GraalDirectives.blackhole(interfaceArrayParameter); + GraalDirectives.blackhole(interfaceField); + GraalDirectives.blackhole(interfaceArrayField); + GraalDirectives.blackhole(interfaceReturn()); + GraalDirectives.blackhole(interfaceArrayReturn()); + GraalDirectives.blackhole(interfaceReturnException()); + GraalDirectives.blackhole(interfaceArrayReturnException()); + } + + public static Runnable interfaceReturn() { + return new A(); + } + + public static Runnable[] interfaceArrayReturn() { + return new Runnable[]{new A(), new B(), new C(), new D()}; + } + + public static Runnable interfaceReturnException() { + return new A(); + } + + public static Runnable[] interfaceArrayReturnException() { + return new Runnable[]{new A(), new B(), new C(), new D()}; + } + + @Override + protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + if (method.getName().startsWith("interfaceReturn") || method.getName().startsWith("interfaceArrayReturn")) { + if (method.getName().equals("Exception")) { + return InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; + } + return InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; + } + return super.bytecodeParserShouldInlineInvoke(b, method, args); + } + + @BeforeClass + public static void setup() { + interfaceArrayReturn(); + } + + @Test + public void test() { + StructuredGraph graph = parseEager("snippet", StructuredGraph.AllowAssumptions.YES); + for (BlackholeNode b : graph.getNodes().filter(BlackholeNode.class)) { + Assert.assertThat(b.getValue(), is(instanceOf(UncheckedInterfaceProvider.class))); + Stamp uncheckedStamp = ((UncheckedInterfaceProvider) b.getValue()).uncheckedStamp(); + String context = b.getValue().toString(Verbosity.Debugger); + Assert.assertNotNull(context, uncheckedStamp); + ResolvedJavaType uncheckedType = StampTool.typeOrNull(uncheckedStamp); + ResolvedJavaType type = StampTool.typeOrNull(b.getValue()); + Assert.assertEquals(context, arrayDepth(type), arrayDepth(uncheckedType)); + Assert.assertTrue(context + ": " + type, type == null || type.getElementalType().isJavaLangObject()); + Assert.assertNotNull(context, uncheckedType); + Assert.assertTrue(context, uncheckedType.getElementalType().isInterface()); + } + } + + private static int arrayDepth(ResolvedJavaType type) { + int depth = 0; + ResolvedJavaType t = type; + while (t != null && t.isArray()) { + depth += 1; + t = t.getComponentType(); + } + return depth; + } + + public static class A implements Runnable { + @Override + public void run() { + // nop + } + } + + public static class B implements Runnable { + @Override + public void run() { + // nop + } + } + + public static class C implements Runnable { + @Override + public void run() { + // nop + } + } + + public static class D implements Runnable { + @Override + public void run() { + // nop + } + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java index f7e0c928304..26a0f899620 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java @@ -22,14 +22,7 @@ */ package org.graalvm.compiler.core.test.deopt; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.InvalidInstalledCodeException; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assert; -import org.junit.Test; - +import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -37,16 +30,19 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; -/** - * In the following tests, the usages of local variable "a" are replaced with the integer constant - * 0. Then canonicalization is applied and it is verified that the resulting graph is equal to the - * graph of the method that just has a "return 1" statement in it. - */ public class CompiledMethodTest extends GraalCompilerTest { public static Object testMethod(Object arg1, Object arg2, Object arg3) { - return arg1 + " " + arg2 + " " + arg3; + String res = arg1 + " " + arg2 + " " + arg3; + return GraalDirectives.inCompiledCode() ? res : "interpreter"; } Object f1; @@ -55,6 +51,12 @@ public class CompiledMethodTest extends GraalCompilerTest { return f1 + " " + arg1 + " " + arg2 + " " + arg3; } + /** + * Usages of the constant {@code " "} are replaced with the constant {@code "-"} and it is + * verified that executing the compiled code produces a result that the preserves the node + * replacement unless deoptimization occurs (e.g., due to -Xcomp causing profiles to be + * missing). + */ @Test public void test1() { final ResolvedJavaMethod javaMethod = getResolvedJavaMethod("testMethod"); @@ -71,7 +73,10 @@ public class CompiledMethodTest extends GraalCompilerTest { InstalledCode compiledMethod = getCode(javaMethod, graph); try { Object result = compiledMethod.executeVarargs("1", "2", "3"); - Assert.assertEquals("1-2-3", result); + if (!"1-2-3".equals(result)) { + // Deoptimization probably occurred + Assert.assertEquals("interpreter", result); + } } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeUnsafeStoreTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeUnsafeStoreTest.java new file mode 100644 index 00000000000..0792e3ca08d --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeUnsafeStoreTest.java @@ -0,0 +1,1001 @@ +/* + * Copyright (c) 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. + */ +package org.graalvm.compiler.core.test.ea; + +import java.lang.reflect.Field; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.junit.Test; + +import sun.misc.Unsafe; + +/** + * Exercise a mix of unsafe and normal reads ands writes in situations where EA might attempt to + * fold the operations. + */ +public class PartialEscapeUnsafeStoreTest extends GraalCompilerTest { + + private static final Unsafe unsafe = initUnsafe(); + + private static Unsafe initUnsafe() { + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + return (Unsafe) theUnsafe.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe", e); + } + } + + private static final long byteArrayBaseOffset = unsafe.arrayBaseOffset(byte[].class); + private static byte byteValue = 0x61; + + public static byte[] testByteArrayWithCharStoreSnippet(char v) { + byte[] b = new byte[8]; + unsafe.putChar(b, byteArrayBaseOffset, v); + return b; + } + + @Test + public void testByteArrayWithCharStore() { + test("testByteArrayWithCharStoreSnippet", charValue); + } + + public static byte[] testByteArrayWithShortStoreSnippet(short v) { + byte[] b = new byte[8]; + unsafe.putShort(b, byteArrayBaseOffset, v); + return b; + } + + @Test + public void testByteArrayWithShortStore() { + test("testByteArrayWithShortStoreSnippet", shortValue); + } + + public static byte[] testByteArrayWithIntStoreSnippet(int v) { + byte[] b = new byte[8]; + unsafe.putInt(b, byteArrayBaseOffset, v); + return b; + } + + @Test + public void testByteArrayWithIntStore() { + test("testByteArrayWithIntStoreSnippet", intValue); + } + + public static byte[] testByteArrayWithLongStoreSnippet(long v) { + byte[] b = new byte[8]; + unsafe.putLong(b, byteArrayBaseOffset, v); + return b; + } + + @Test + public void testByteArrayWithLongStore() { + test("testByteArrayWithLongStoreSnippet", longValue); + } + + public static byte[] testByteArrayWithFloatStoreSnippet(float v) { + byte[] b = new byte[8]; + unsafe.putFloat(b, byteArrayBaseOffset, v); + return b; + } + + @Test + public void testByteArrayWithFloatStore() { + test("testByteArrayWithFloatStoreSnippet", floatValue); + } + + public static byte[] testByteArrayWithDoubleStoreSnippet(double v) { + byte[] b = new byte[8]; + unsafe.putDouble(b, byteArrayBaseOffset, v); + return b; + } + + @Test + public void testByteArrayWithDoubleStore() { + test("testByteArrayWithDoubleStoreSnippet", doubleValue); + } + + private static final long charArrayBaseOffset = unsafe.arrayBaseOffset(char[].class); + private static char charValue = 0x4142; + + public static char[] testCharArrayWithByteStoreSnippet(byte v) { + char[] b = new char[4]; + unsafe.putByte(b, charArrayBaseOffset, v); + return b; + } + + @Test + public void testCharArrayWithByteStore() { + test("testCharArrayWithByteStoreSnippet", byteValue); + } + + public static char[] testCharArrayWithShortStoreSnippet(short v) { + char[] b = new char[4]; + unsafe.putShort(b, charArrayBaseOffset, v); + return b; + } + + @Test + public void testCharArrayWithShortStore() { + test("testCharArrayWithShortStoreSnippet", shortValue); + } + + public static char[] testCharArrayWithIntStoreSnippet(int v) { + char[] b = new char[4]; + unsafe.putInt(b, charArrayBaseOffset, v); + return b; + } + + @Test + public void testCharArrayWithIntStore() { + test("testCharArrayWithIntStoreSnippet", intValue); + } + + public static char[] testCharArrayWithLongStoreSnippet(long v) { + char[] b = new char[4]; + unsafe.putLong(b, charArrayBaseOffset, v); + return b; + } + + @Test + public void testCharArrayWithLongStore() { + test("testCharArrayWithLongStoreSnippet", longValue); + } + + public static char[] testCharArrayWithFloatStoreSnippet(float v) { + char[] b = new char[4]; + unsafe.putFloat(b, charArrayBaseOffset, v); + return b; + } + + @Test + public void testCharArrayWithFloatStore() { + test("testCharArrayWithFloatStoreSnippet", floatValue); + } + + public static char[] testCharArrayWithDoubleStoreSnippet(double v) { + char[] b = new char[4]; + unsafe.putDouble(b, charArrayBaseOffset, v); + return b; + } + + @Test + public void testCharArrayWithDoubleStore() { + test("testCharArrayWithDoubleStoreSnippet", doubleValue); + } + + private static final long shortArrayBaseOffset = unsafe.arrayBaseOffset(short[].class); + private static short shortValue = 0x1112; + + public static short[] testShortArrayWithByteStoreSnippet(byte v) { + short[] b = new short[4]; + unsafe.putByte(b, shortArrayBaseOffset, v); + return b; + } + + @Test + public void testShortArrayWithByteStore() { + test("testShortArrayWithByteStoreSnippet", byteValue); + } + + public static short[] testShortArrayWithCharStoreSnippet(char v) { + short[] b = new short[4]; + unsafe.putChar(b, shortArrayBaseOffset, v); + return b; + } + + @Test + public void testShortArrayWithCharStore() { + test("testShortArrayWithCharStoreSnippet", charValue); + } + + public static short[] testShortArrayWithIntStoreSnippet(int v) { + short[] b = new short[4]; + unsafe.putInt(b, shortArrayBaseOffset, v); + return b; + } + + @Test + public void testShortArrayWithIntStore() { + test("testShortArrayWithIntStoreSnippet", intValue); + } + + public static short[] testShortArrayWithLongStoreSnippet(long v) { + short[] b = new short[4]; + unsafe.putLong(b, shortArrayBaseOffset, v); + return b; + } + + @Test + public void testShortArrayWithLongStore() { + test("testShortArrayWithLongStoreSnippet", longValue); + } + + public static short[] testShortArrayWithFloatStoreSnippet(float v) { + short[] b = new short[4]; + unsafe.putFloat(b, shortArrayBaseOffset, v); + return b; + } + + @Test + public void testShortArrayWithFloatStore() { + test("testShortArrayWithFloatStoreSnippet", floatValue); + } + + public static short[] testShortArrayWithDoubleStoreSnippet(double v) { + short[] b = new short[4]; + unsafe.putDouble(b, shortArrayBaseOffset, v); + return b; + } + + @Test + public void testShortArrayWithDoubleStore() { + test("testShortArrayWithDoubleStoreSnippet", doubleValue); + } + + private static final long intArrayBaseOffset = unsafe.arrayBaseOffset(int[].class); + private static int intValue = 0x01020304; + + public static int[] testIntArrayWithByteStoreSnippet(byte v) { + int[] b = new int[4]; + unsafe.putByte(b, intArrayBaseOffset, v); + return b; + } + + @Test + public void testIntArrayWithByteStore() { + test("testIntArrayWithByteStoreSnippet", byteValue); + } + + public static int[] testIntArrayWithCharStoreSnippet(char v) { + int[] b = new int[4]; + unsafe.putChar(b, intArrayBaseOffset, v); + return b; + } + + @Test + public void testIntArrayWithCharStore() { + test("testIntArrayWithCharStoreSnippet", charValue); + } + + public static int[] testIntArrayWithShortStoreSnippet(short v) { + int[] b = new int[4]; + unsafe.putShort(b, intArrayBaseOffset, v); + return b; + } + + @Test + public void testIntArrayWithShortStore() { + test("testIntArrayWithShortStoreSnippet", shortValue); + } + + public static int[] testIntArrayWithLongStoreSnippet(long v) { + int[] b = new int[4]; + unsafe.putLong(b, intArrayBaseOffset, v); + return b; + } + + @Test + public void testIntArrayWithLongStore() { + test("testIntArrayWithLongStoreSnippet", longValue); + } + + public static int[] testIntArrayWithFloatStoreSnippet(float v) { + int[] b = new int[4]; + unsafe.putFloat(b, intArrayBaseOffset, v); + return b; + } + + @Test + public void testIntArrayWithFloatStore() { + test("testIntArrayWithFloatStoreSnippet", floatValue); + } + + public static int[] testIntArrayWithDoubleStoreSnippet(double v) { + int[] b = new int[4]; + unsafe.putDouble(b, intArrayBaseOffset, v); + return b; + } + + @Test + public void testIntArrayWithDoubleStore() { + test("testIntArrayWithDoubleStoreSnippet", doubleValue); + } + + private static final long longArrayBaseOffset = unsafe.arrayBaseOffset(long[].class); + private static long longValue = 0x31323334353637L; + + public static long[] testLongArrayWithByteStoreSnippet(byte v) { + long[] b = new long[4]; + unsafe.putByte(b, longArrayBaseOffset, v); + return b; + } + + @Test + public void testLongArrayWithByteStore() { + test("testLongArrayWithByteStoreSnippet", byteValue); + } + + public static long[] testLongArrayWithCharStoreSnippet(char v) { + long[] b = new long[4]; + unsafe.putChar(b, longArrayBaseOffset, v); + return b; + } + + @Test + public void testLongArrayWithCharStore() { + test("testLongArrayWithCharStoreSnippet", charValue); + } + + public static long[] testLongArrayWithShortStoreSnippet(short v) { + long[] b = new long[4]; + unsafe.putShort(b, longArrayBaseOffset, v); + return b; + } + + @Test + public void testLongArrayWithShortStore() { + test("testLongArrayWithShortStoreSnippet", shortValue); + } + + public static long[] testLongArrayWithIntStoreSnippet(int v) { + long[] b = new long[4]; + unsafe.putInt(b, longArrayBaseOffset, v); + return b; + } + + @Test + public void testLongArrayWithIntStore() { + test("testLongArrayWithIntStoreSnippet", intValue); + } + + public static long[] testLongArrayWithFloatStoreSnippet(float v) { + long[] b = new long[4]; + unsafe.putFloat(b, longArrayBaseOffset, v); + return b; + } + + @Test + public void testLongArrayWithFloatStore() { + test("testLongArrayWithFloatStoreSnippet", floatValue); + } + + public static long[] testLongArrayWithDoubleStoreSnippet(double v) { + long[] b = new long[4]; + unsafe.putDouble(b, longArrayBaseOffset, v); + return b; + } + + @Test + public void testLongArrayWithDoubleStore() { + test("testLongArrayWithDoubleStoreSnippet", doubleValue); + } + + private static final long floatArrayBaseOffset = unsafe.arrayBaseOffset(float[].class); + private static float floatValue = Float.NaN; + + public static float[] testFloatArrayWithByteStoreSnippet(byte v) { + float[] b = new float[4]; + unsafe.putByte(b, floatArrayBaseOffset, v); + return b; + } + + @Test + public void testFloatArrayWithByteStore() { + test("testFloatArrayWithByteStoreSnippet", byteValue); + } + + public static float[] testFloatArrayWithCharStoreSnippet(char v) { + float[] b = new float[4]; + unsafe.putChar(b, floatArrayBaseOffset, v); + return b; + } + + @Test + public void testFloatArrayWithCharStore() { + test("testFloatArrayWithCharStoreSnippet", charValue); + } + + public static float[] testFloatArrayWithShortStoreSnippet(short v) { + float[] b = new float[4]; + unsafe.putShort(b, floatArrayBaseOffset, v); + return b; + } + + @Test + public void testFloatArrayWithShortStore() { + test("testFloatArrayWithShortStoreSnippet", shortValue); + } + + public static float[] testFloatArrayWithIntStoreSnippet(int v) { + float[] b = new float[4]; + unsafe.putInt(b, floatArrayBaseOffset, v); + return b; + } + + @Test + public void testFloatArrayWithIntStore() { + test("testFloatArrayWithIntStoreSnippet", intValue); + } + + public static float[] testFloatArrayWithLongStoreSnippet(long v) { + float[] b = new float[4]; + unsafe.putLong(b, floatArrayBaseOffset, v); + return b; + } + + @Test + public void testFloatArrayWithLongStore() { + test("testFloatArrayWithLongStoreSnippet", longValue); + } + + public static float[] testFloatArrayWithDoubleStoreSnippet(double v) { + float[] b = new float[4]; + unsafe.putDouble(b, floatArrayBaseOffset, v); + return b; + } + + @Test + public void testFloatArrayWithDoubleStore() { + test("testFloatArrayWithDoubleStoreSnippet", doubleValue); + } + + private static final long doubleArrayBaseOffset = unsafe.arrayBaseOffset(double[].class); + private static double doubleValue = Double.NaN; + private static final int byteSize = 1; + private static final int charSize = 2; + private static final int shortSize = 2; + private static final int intSize = 4; + private static final int floatSize = 4; + private static final int longSize = 8; + private static final int doubleSize = 8; + + public static double[] testDoubleArrayWithByteStoreSnippet(byte v) { + double[] b = new double[4]; + unsafe.putByte(b, doubleArrayBaseOffset, v); + return b; + } + + @Test + public void testDoubleArrayWithByteStore() { + test("testDoubleArrayWithByteStoreSnippet", byteValue); + } + + public static double[] testDoubleArrayWithCharStoreSnippet(char v) { + double[] b = new double[4]; + unsafe.putChar(b, doubleArrayBaseOffset, v); + return b; + } + + @Test + public void testDoubleArrayWithCharStore() { + test("testDoubleArrayWithCharStoreSnippet", charValue); + } + + public static double[] testDoubleArrayWithShortStoreSnippet(short v) { + double[] b = new double[4]; + unsafe.putShort(b, doubleArrayBaseOffset, v); + return b; + } + + @Test + public void testDoubleArrayWithShortStore() { + test("testDoubleArrayWithShortStoreSnippet", shortValue); + } + + public static double[] testDoubleArrayWithIntStoreSnippet(int v) { + double[] b = new double[4]; + unsafe.putInt(b, doubleArrayBaseOffset, v); + return b; + } + + @Test + public void testDoubleArrayWithIntStore() { + test("testDoubleArrayWithIntStoreSnippet", intValue); + } + + public static double[] testDoubleArrayWithLongStoreSnippet(long v) { + double[] b = new double[4]; + unsafe.putLong(b, doubleArrayBaseOffset, v); + return b; + } + + @Test + public void testDoubleArrayWithLongStore() { + test("testDoubleArrayWithLongStoreSnippet", longValue); + } + + public static double[] testDoubleArrayWithFloatStoreSnippet(float v) { + double[] b = new double[4]; + unsafe.putFloat(b, doubleArrayBaseOffset, v); + return b; + } + + @Test + public void testDoubleArrayWithFloatStore() { + test("testDoubleArrayWithFloatStoreSnippet", floatValue); + } + + public static byte testByteArrayWithCharStoreAndReadSnippet(char v) { + byte[] b = new byte[4]; + unsafe.putChar(b, byteArrayBaseOffset, v); + return b[(byteSize / charSize) + 1]; + } + + @Test + public void testByteArrayWithCharStoreAndRead() { + test("testByteArrayWithCharStoreAndReadSnippet", charValue); + } + + public static byte testByteArrayWithShortStoreAndReadSnippet(short v) { + byte[] b = new byte[4]; + unsafe.putShort(b, byteArrayBaseOffset, v); + return b[(byteSize / shortSize) + 1]; + } + + @Test + public void testByteArrayWithShortStoreAndRead() { + test("testByteArrayWithShortStoreAndReadSnippet", shortValue); + } + + public static byte testByteArrayWithIntStoreAndReadSnippet(int v) { + byte[] b = new byte[4]; + unsafe.putInt(b, byteArrayBaseOffset, v); + return b[(byteSize / intSize) + 1]; + } + + @Test + public void testByteArrayWithIntStoreAndRead() { + test("testByteArrayWithIntStoreAndReadSnippet", intValue); + } + + public static byte testByteArrayWithLongStoreAndReadSnippet(long v) { + byte[] b = new byte[4]; + unsafe.putLong(b, byteArrayBaseOffset, v); + return b[(byteSize / longSize) + 1]; + } + + @Test + public void testByteArrayWithLongStoreAndRead() { + test("testByteArrayWithLongStoreAndReadSnippet", longValue); + } + + public static byte testByteArrayWithFloatStoreAndReadSnippet(float v) { + byte[] b = new byte[4]; + unsafe.putFloat(b, byteArrayBaseOffset, v); + return b[(byteSize / floatSize) + 1]; + } + + @Test + public void testByteArrayWithFloatStoreAndRead() { + test("testByteArrayWithFloatStoreAndReadSnippet", floatValue); + } + + public static byte testByteArrayWithDoubleStoreAndReadSnippet(double v) { + byte[] b = new byte[4]; + unsafe.putDouble(b, byteArrayBaseOffset, v); + return b[(byteSize / doubleSize) + 1]; + } + + @Test + public void testByteArrayWithDoubleStoreAndRead() { + test("testByteArrayWithDoubleStoreAndReadSnippet", doubleValue); + } + + public static char testCharArrayWithByteStoreAndReadSnippet(byte v) { + char[] b = new char[4]; + unsafe.putByte(b, charArrayBaseOffset, v); + return b[(charSize / byteSize) + 1]; + } + + @Test + public void testCharArrayWithByteStoreAndRead() { + test("testCharArrayWithByteStoreAndReadSnippet", byteValue); + } + + public static char testCharArrayWithShortStoreAndReadSnippet(short v) { + char[] b = new char[4]; + unsafe.putShort(b, charArrayBaseOffset, v); + return b[(charSize / shortSize) + 1]; + } + + @Test + public void testCharArrayWithShortStoreAndRead() { + test("testCharArrayWithShortStoreAndReadSnippet", shortValue); + } + + public static char testCharArrayWithIntStoreAndReadSnippet(int v) { + char[] b = new char[4]; + unsafe.putInt(b, charArrayBaseOffset, v); + return b[(charSize / intSize) + 1]; + } + + @Test + public void testCharArrayWithIntStoreAndRead() { + test("testCharArrayWithIntStoreAndReadSnippet", intValue); + } + + public static char testCharArrayWithLongStoreAndReadSnippet(long v) { + char[] b = new char[4]; + unsafe.putLong(b, charArrayBaseOffset, v); + return b[(charSize / longSize) + 1]; + } + + @Test + public void testCharArrayWithLongStoreAndRead() { + test("testCharArrayWithLongStoreAndReadSnippet", longValue); + } + + public static char testCharArrayWithFloatStoreAndReadSnippet(float v) { + char[] b = new char[4]; + unsafe.putFloat(b, charArrayBaseOffset, v); + return b[(charSize / floatSize) + 1]; + } + + @Test + public void testCharArrayWithFloatStoreAndRead() { + test("testCharArrayWithFloatStoreAndReadSnippet", floatValue); + } + + public static char testCharArrayWithDoubleStoreAndReadSnippet(double v) { + char[] b = new char[4]; + unsafe.putDouble(b, charArrayBaseOffset, v); + return b[(charSize / doubleSize) + 1]; + } + + @Test + public void testCharArrayWithDoubleStoreAndRead() { + test("testCharArrayWithDoubleStoreAndReadSnippet", doubleValue); + } + + public static short testShortArrayWithByteStoreAndReadSnippet(byte v) { + short[] b = new short[4]; + unsafe.putByte(b, shortArrayBaseOffset, v); + return b[(shortSize / byteSize) + 1]; + } + + @Test + public void testShortArrayWithByteStoreAndRead() { + test("testShortArrayWithByteStoreAndReadSnippet", byteValue); + } + + public static short testShortArrayWithCharStoreAndReadSnippet(char v) { + short[] b = new short[4]; + unsafe.putChar(b, shortArrayBaseOffset, v); + return b[(shortSize / charSize) + 1]; + } + + @Test + public void testShortArrayWithCharStoreAndRead() { + test("testShortArrayWithCharStoreAndReadSnippet", charValue); + } + + public static short testShortArrayWithIntStoreAndReadSnippet(int v) { + short[] b = new short[4]; + unsafe.putInt(b, shortArrayBaseOffset, v); + return b[(shortSize / intSize) + 1]; + } + + @Test + public void testShortArrayWithIntStoreAndRead() { + test("testShortArrayWithIntStoreAndReadSnippet", intValue); + } + + public static short testShortArrayWithLongStoreAndReadSnippet(long v) { + short[] b = new short[4]; + unsafe.putLong(b, shortArrayBaseOffset, v); + return b[(shortSize / longSize) + 1]; + } + + @Test + public void testShortArrayWithLongStoreAndRead() { + test("testShortArrayWithLongStoreAndReadSnippet", longValue); + } + + public static short testShortArrayWithFloatStoreAndReadSnippet(float v) { + short[] b = new short[4]; + unsafe.putFloat(b, shortArrayBaseOffset, v); + return b[(shortSize / floatSize) + 1]; + } + + @Test + public void testShortArrayWithFloatStoreAndRead() { + test("testShortArrayWithFloatStoreAndReadSnippet", floatValue); + } + + public static short testShortArrayWithDoubleStoreAndReadSnippet(double v) { + short[] b = new short[4]; + unsafe.putDouble(b, shortArrayBaseOffset, v); + return b[(shortSize / doubleSize) + 1]; + } + + @Test + public void testShortArrayWithDoubleStoreAndRead() { + test("testShortArrayWithDoubleStoreAndReadSnippet", doubleValue); + } + + public static int testIntArrayWithByteStoreAndReadSnippet(byte v) { + int[] b = new int[4]; + unsafe.putByte(b, intArrayBaseOffset, v); + return b[(intSize / byteSize) + 1]; + } + + @Test + public void testIntArrayWithByteStoreAndRead() { + test("testIntArrayWithByteStoreAndReadSnippet", byteValue); + } + + public static int testIntArrayWithCharStoreAndReadSnippet(char v) { + int[] b = new int[4]; + unsafe.putChar(b, intArrayBaseOffset, v); + return b[(intSize / charSize) + 1]; + } + + @Test + public void testIntArrayWithCharStoreAndRead() { + test("testIntArrayWithCharStoreAndReadSnippet", charValue); + } + + public static int testIntArrayWithShortStoreAndReadSnippet(short v) { + int[] b = new int[4]; + unsafe.putShort(b, intArrayBaseOffset, v); + return b[(intSize / shortSize) + 1]; + } + + @Test + public void testIntArrayWithShortStoreAndRead() { + test("testIntArrayWithShortStoreAndReadSnippet", shortValue); + } + + public static int testIntArrayWithLongStoreAndReadSnippet(long v) { + int[] b = new int[4]; + unsafe.putLong(b, intArrayBaseOffset, v); + return b[(intSize / longSize) + 1]; + } + + @Test + public void testIntArrayWithLongStoreAndRead() { + test("testIntArrayWithLongStoreAndReadSnippet", longValue); + } + + public static int testIntArrayWithFloatStoreAndReadSnippet(float v) { + int[] b = new int[4]; + unsafe.putFloat(b, intArrayBaseOffset, v); + return b[(intSize / floatSize) + 1]; + } + + @Test + public void testIntArrayWithFloatStoreAndRead() { + test("testIntArrayWithFloatStoreAndReadSnippet", floatValue); + } + + public static int testIntArrayWithDoubleStoreAndReadSnippet(double v) { + int[] b = new int[4]; + unsafe.putDouble(b, intArrayBaseOffset, v); + return b[(intSize / doubleSize) + 1]; + } + + @Test + public void testIntArrayWithDoubleStoreAndRead() { + test("testIntArrayWithDoubleStoreAndReadSnippet", doubleValue); + } + + public static long testLongArrayWithByteStoreAndReadSnippet(byte v) { + long[] b = new long[4]; + unsafe.putByte(b, longArrayBaseOffset, v); + return b[(longSize / byteSize) + 1]; + } + + @Test + public void testLongArrayWithByteStoreAndRead() { + test("testLongArrayWithByteStoreAndReadSnippet", byteValue); + } + + public static long testLongArrayWithCharStoreAndReadSnippet(char v) { + long[] b = new long[4]; + unsafe.putChar(b, longArrayBaseOffset, v); + return b[(longSize / charSize) + 1]; + } + + @Test + public void testLongArrayWithCharStoreAndRead() { + test("testLongArrayWithCharStoreAndReadSnippet", charValue); + } + + public static long testLongArrayWithShortStoreAndReadSnippet(short v) { + long[] b = new long[4]; + unsafe.putShort(b, longArrayBaseOffset, v); + return b[(longSize / shortSize) + 1]; + } + + @Test + public void testLongArrayWithShortStoreAndRead() { + test("testLongArrayWithShortStoreAndReadSnippet", shortValue); + } + + public static long testLongArrayWithIntStoreAndReadSnippet(int v) { + long[] b = new long[4]; + unsafe.putInt(b, longArrayBaseOffset, v); + return b[(longSize / intSize) + 1]; + } + + @Test + public void testLongArrayWithIntStoreAndRead() { + test("testLongArrayWithIntStoreAndReadSnippet", intValue); + } + + public static long testLongArrayWithFloatStoreAndReadSnippet(float v) { + long[] b = new long[4]; + unsafe.putFloat(b, longArrayBaseOffset, v); + return b[(longSize / floatSize) + 1]; + } + + @Test + public void testLongArrayWithFloatStoreAndRead() { + test("testLongArrayWithFloatStoreAndReadSnippet", floatValue); + } + + public static long testLongArrayWithDoubleStoreAndReadSnippet(double v) { + long[] b = new long[4]; + unsafe.putDouble(b, longArrayBaseOffset, v); + return b[(longSize / doubleSize) + 1]; + } + + @Test + public void testLongArrayWithDoubleStoreAndRead() { + test("testLongArrayWithDoubleStoreAndReadSnippet", doubleValue); + } + + public static float testFloatArrayWithByteStoreAndReadSnippet(byte v) { + float[] b = new float[4]; + unsafe.putByte(b, floatArrayBaseOffset, v); + return b[(floatSize / byteSize) + 1]; + } + + @Test + public void testFloatArrayWithByteStoreAndRead() { + test("testFloatArrayWithByteStoreAndReadSnippet", byteValue); + } + + public static float testFloatArrayWithCharStoreAndReadSnippet(char v) { + float[] b = new float[4]; + unsafe.putChar(b, floatArrayBaseOffset, v); + return b[(floatSize / charSize) + 1]; + } + + @Test + public void testFloatArrayWithCharStoreAndRead() { + test("testFloatArrayWithCharStoreAndReadSnippet", charValue); + } + + public static float testFloatArrayWithShortStoreAndReadSnippet(short v) { + float[] b = new float[4]; + unsafe.putShort(b, floatArrayBaseOffset, v); + return b[(floatSize / shortSize) + 1]; + } + + @Test + public void testFloatArrayWithShortStoreAndRead() { + test("testFloatArrayWithShortStoreAndReadSnippet", shortValue); + } + + public static float testFloatArrayWithIntStoreAndReadSnippet(int v) { + float[] b = new float[4]; + unsafe.putInt(b, floatArrayBaseOffset, v); + return b[(floatSize / intSize) + 1]; + } + + @Test + public void testFloatArrayWithIntStoreAndRead() { + test("testFloatArrayWithIntStoreAndReadSnippet", intValue); + } + + public static float testFloatArrayWithLongStoreAndReadSnippet(long v) { + float[] b = new float[4]; + unsafe.putLong(b, floatArrayBaseOffset, v); + return b[(floatSize / longSize) + 1]; + } + + @Test + public void testFloatArrayWithLongStoreAndRead() { + test("testFloatArrayWithLongStoreAndReadSnippet", longValue); + } + + public static float testFloatArrayWithDoubleStoreAndReadSnippet(double v) { + float[] b = new float[4]; + unsafe.putDouble(b, floatArrayBaseOffset, v); + return b[(floatSize / doubleSize) + 1]; + } + + @Test + public void testFloatArrayWithDoubleStoreAndRead() { + test("testFloatArrayWithDoubleStoreAndReadSnippet", doubleValue); + } + + public static double testDoubleArrayWithByteStoreAndReadSnippet(byte v) { + double[] b = new double[4]; + unsafe.putByte(b, doubleArrayBaseOffset, v); + return b[(doubleSize / byteSize) + 1]; + } + + @Test + public void testDoubleArrayWithByteStoreAndRead() { + test("testDoubleArrayWithByteStoreAndReadSnippet", byteValue); + } + + public static double testDoubleArrayWithCharStoreAndReadSnippet(char v) { + double[] b = new double[4]; + unsafe.putChar(b, doubleArrayBaseOffset, v); + return b[(doubleSize / charSize) + 1]; + } + + @Test + public void testDoubleArrayWithCharStoreAndRead() { + test("testDoubleArrayWithCharStoreAndReadSnippet", charValue); + } + + public static double testDoubleArrayWithShortStoreAndReadSnippet(short v) { + double[] b = new double[4]; + unsafe.putShort(b, doubleArrayBaseOffset, v); + return b[(doubleSize / shortSize) + 1]; + } + + @Test + public void testDoubleArrayWithShortStoreAndRead() { + test("testDoubleArrayWithShortStoreAndReadSnippet", shortValue); + } + + public static double testDoubleArrayWithIntStoreAndReadSnippet(int v) { + double[] b = new double[4]; + unsafe.putInt(b, doubleArrayBaseOffset, v); + return b[(doubleSize / intSize) + 1]; + } + + @Test + public void testDoubleArrayWithIntStoreAndRead() { + test("testDoubleArrayWithIntStoreAndReadSnippet", intValue); + } + + public static double testDoubleArrayWithLongStoreAndReadSnippet(long v) { + double[] b = new double[4]; + unsafe.putLong(b, doubleArrayBaseOffset, v); + return b[(doubleSize / longSize) + 1]; + } + + @Test + public void testDoubleArrayWithLongStoreAndRead() { + test("testDoubleArrayWithLongStoreAndReadSnippet", longValue); + } + + public static double testDoubleArrayWithFloatStoreAndReadSnippet(float v) { + double[] b = new double[4]; + unsafe.putFloat(b, doubleArrayBaseOffset, v); + return b[(doubleSize / floatSize) + 1]; + } + + @Test + public void testDoubleArrayWithFloatStoreAndRead() { + test("testDoubleArrayWithFloatStoreAndReadSnippet", floatValue); + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/PolymorphicInliningTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/PolymorphicInliningTest.java new file mode 100644 index 00000000000..015add57c38 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/PolymorphicInliningTest.java @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2012, 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. + */ +package org.graalvm.compiler.core.test.inlining; + +import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; +import static org.graalvm.compiler.test.SubprocessUtil.java; +import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; + +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugDumpScope; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.DeoptimizeNode; +import org.graalvm.compiler.nodes.InvokeNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.nodes.java.TypeSwitchNode; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; +import org.graalvm.compiler.phases.common.inlining.InliningPhase; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.test.SubprocessUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +public class PolymorphicInliningTest extends GraalCompilerTest { + + @Test + public void testInSubprocess() throws InterruptedException, IOException { + String recursionPropName = getClass().getName() + ".recursion"; + if (Boolean.getBoolean(recursionPropName)) { + testPolymorphicInlining(); + testPolymorphicNotInlining(); + testMegamorphicInlining(); + testMegamorphicNotInlining(); + } else { + List vmArgs = withoutDebuggerArguments(getVMCommandLine()); + NotInlinableSubClass.class.getCanonicalName(); + vmArgs.add("-XX:CompileCommand=dontinline,org/graalvm/compiler/core/test/inlining/PolymorphicInliningTest$NotInlinableSubClass.publicOverriddenMethod"); + vmArgs.add("-D" + recursionPropName + "=true"); + SubprocessUtil.Subprocess proc = java(vmArgs, "com.oracle.mxtool.junit.MxJUnitWrapper", getClass().getName()); + if (proc.exitCode != 0) { + Assert.fail(String.format("non-zero exit code %d for command:%n%s", proc.exitCode, proc)); + } + } + } + + public int polymorphicCallsite(SuperClass receiver) { + return receiver.publicOverriddenMethod(); + } + + public void testPolymorphicInlining() { + for (int i = 0; i < 10000; i++) { + if (i % 2 == 0) { + polymorphicCallsite(Receivers.subClassA); + } else { + polymorphicCallsite(Receivers.subClassB); + } + } + StructuredGraph graph = getGraph("polymorphicCallsite", false); + // This callsite should be inlined with a TypeCheckedInliningViolated deoptimization. + assertTrue(getNodeCount(graph, InvokeNode.class) == 0); + assertTrue(getNodeCount(graph, TypeSwitchNode.class) == 1); + assertTrue(getNodeCount(graph, DeoptimizeNode.class) >= 1); + } + + /** + * This snippet is identical to {@link #polymorphicCallsite(SuperClass)}, and is for avoiding + * interference of the receiver type profile from different unit tests. + */ + public int polymorphicCallsite1(SuperClass receiver) { + return receiver.publicOverriddenMethod(); + } + + public void testPolymorphicNotInlining() { + for (int i = 0; i < 10000; i++) { + if (i % 2 == 0) { + polymorphicCallsite1(Receivers.subClassA); + } else { + polymorphicCallsite1(Receivers.notInlinableSubClass); + } + } + StructuredGraph graph = getGraph("polymorphicCallsite1", false); + // This callsite should not be inlined due to one of the potential callee method is not + // inlinable. + assertTrue(getNodeCount(graph, InvokeNode.class) == 1); + assertTrue(getNodeCount(graph, TypeSwitchNode.class) == 0); + } + + /** + * This snippet is identical to {@link #polymorphicCallsite(SuperClass)}, and is for avoiding + * interference of the receiver type profile from different unit tests. + */ + public int polymorphicCallsite2(SuperClass receiver) { + return receiver.publicOverriddenMethod(); + } + + public void testMegamorphicInlining() { + // Construct a receiver type profile that exceeds the max type width (by default 8 in JVMCI, + // specified by -XX:TypeProfileWidth). + for (int i = 0; i < 2000; i++) { + // Ensure the following receiver type is within the type profile. + polymorphicCallsite2(Receivers.subClassA); + } + for (int i = 0; i < 10000; i++) { + switch (i % 20) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + // Probability: 40% + // Ensure the probability is greater than + // GraalOptions.MegamorphicInliningMinMethodProbability (by default 0.33D); + polymorphicCallsite2(Receivers.subClassA); + break; + case 8: + polymorphicCallsite2(Receivers.subClassB); + break; + case 9: + polymorphicCallsite2(Receivers.subClassC); + break; + case 10: + polymorphicCallsite2(Receivers.subClassD); + break; + case 11: + polymorphicCallsite2(Receivers.subClassE); + break; + case 12: + polymorphicCallsite2(Receivers.subClassF); + break; + case 13: + polymorphicCallsite2(Receivers.subClassG); + break; + case 14: + polymorphicCallsite2(Receivers.subClassH); + break; + default: + // Probability: 25% + polymorphicCallsite2(Receivers.notInlinableSubClass); + break; + } + } + StructuredGraph graph = getGraph("polymorphicCallsite2", false); + // This callsite should be inlined with a fallback invocation. + assertTrue(getNodeCount(graph, InvokeNode.class) == 1); + assertTrue(getNodeCount(graph, TypeSwitchNode.class) == 1); + } + + /** + * This snippet is identical to {@link #polymorphicCallsite(SuperClass)}, and is for avoiding + * interference of the receiver type profile from different unit tests. + */ + public int polymorphicCallsite3(SuperClass receiver) { + return receiver.publicOverriddenMethod(); + } + + public void testMegamorphicNotInlining() { + for (int i = 0; i < 10000; i++) { + switch (i % 10) { + case 0: + case 1: + polymorphicCallsite3(Receivers.subClassA); + break; + case 2: + polymorphicCallsite3(Receivers.subClassB); + break; + case 3: + polymorphicCallsite3(Receivers.subClassC); + break; + case 4: + polymorphicCallsite3(Receivers.subClassD); + break; + case 5: + polymorphicCallsite3(Receivers.subClassE); + break; + case 6: + polymorphicCallsite3(Receivers.subClassF); + break; + case 7: + polymorphicCallsite3(Receivers.subClassG); + break; + case 8: + polymorphicCallsite3(Receivers.subClassH); + break; + default: + polymorphicCallsite3(Receivers.notInlinableSubClass); + break; + } + } + StructuredGraph graph = getGraph("polymorphicCallsite3", false); + // This callsite should not be inlined due to non of the potential callee method exceeds the + // probability specified by GraalOptions.MegamorphicInliningMinMethodProbability. + assertTrue(getNodeCount(graph, InvokeNode.class) == 1); + assertTrue(getNodeCount(graph, TypeSwitchNode.class) == 0); + } + + @SuppressWarnings("try") + private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("InliningTest", new DebugDumpScope(snippet, true))) { + ResolvedJavaMethod method = getResolvedJavaMethod(snippet); + Builder builder = builder(method, AllowAssumptions.YES, debug); + StructuredGraph graph = eagerInfopointMode ? parse(builder, getDebugGraphBuilderSuite()) : parse(builder, getEagerGraphBuilderSuite()); + try (DebugContext.Scope s2 = debug.scope("Inlining", graph)) { + PhaseSuite graphBuilderSuite = eagerInfopointMode + ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)) + : getDefaultGraphBuilderSuite(); + HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); + new CanonicalizerPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase()).apply(graph, context); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); + new CanonicalizerPhase().apply(graph, context); + new DeadCodeEliminationPhase().apply(graph); + return graph; + } + } catch (Throwable e) { + throw debug.handle(e); + } + } + + private static int getNodeCount(StructuredGraph graph, Class nodeClass) { + return graph.getNodes().filter(nodeClass).count(); + } + + private static final class Receivers { + static final SubClassA subClassA = new SubClassA(); + static final SubClassB subClassB = new SubClassB(); + static final SubClassC subClassC = new SubClassC(); + static final SubClassD subClassD = new SubClassD(); + static final SubClassE subClassE = new SubClassE(); + static final SubClassF subClassF = new SubClassF(); + static final SubClassG subClassG = new SubClassG(); + static final SubClassH subClassH = new SubClassH(); + + static final NotInlinableSubClass notInlinableSubClass = new NotInlinableSubClass(); + } + + private abstract static class SuperClass { + + public abstract int publicOverriddenMethod(); + + } + + private static class SubClassA extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'A'; + } + + } + + private static class SubClassB extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'B'; + } + + } + + private static class SubClassC extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'C'; + } + + } + + private static class SubClassD extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'D'; + } + + } + + private static class SubClassE extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'E'; + } + + } + + private static class SubClassF extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'F'; + } + + } + + private static class SubClassG extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'G'; + } + + } + + private static class SubClassH extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'H'; + } + + } + + private static final class NotInlinableSubClass extends SuperClass { + + @Override + public int publicOverriddenMethod() { + return 'X'; + } + + } + +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java index fffe121e077..a151bc46c28 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java @@ -81,6 +81,7 @@ import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoweredCallTargetNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -243,7 +244,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } protected LIRKind getExactPhiKind(PhiNode phi) { - LIRKind derivedKind = gen.toRegisterKind(gen.getLIRKind(phi.stamp())); + LIRKind derivedKind = gen.toRegisterKind(gen.getLIRKind(phi.stamp(NodeView.DEFAULT))); /* Collect reference information. */ for (int i = 0; i < phi.valueCount() && !derivedKind.isUnknownReference(); i++) { ValueNode node = phi.valueAt(i); @@ -255,7 +256,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio valueKind = value.getValueKind(LIRKind.class); } else { assert isPhiInputFromBackedge(phi, i) : String.format("Input %s to phi node %s is not yet available although it is not coming from a loop back edge", node, phi); - LIRKind kind = gen.getLIRKind(node.stamp()); + LIRKind kind = gen.getLIRKind(node.stamp(NodeView.DEFAULT)); valueKind = gen.toRegisterKind(kind); } /* Merge the reference information of the derived kind and the input. */ @@ -448,7 +449,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } protected void emitNode(ValueNode node) { - if (node.getDebug().isLogEnabled() && node.stamp().isEmpty()) { + if (node.getDebug().isLogEnabled() && node.stamp(NodeView.DEFAULT).isEmpty()) { node.getDebug().log("This node has an empty stamp, we are emitting dead code(?): %s", node); } setSourcePosition(node.getNodeSourcePosition()); @@ -477,7 +478,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { Value paramValue = params[param.index()]; - assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp())) : paramValue + " " + getLIRGeneratorTool().getLIRKind(param.stamp()); + assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp(NodeView.DEFAULT))) : paramValue + " " + + getLIRGeneratorTool().getLIRKind(param.stamp(NodeView.DEFAULT)); setResult(param, gen.emitMove(paramValue)); } } @@ -506,7 +508,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } protected LIRKind getPhiKind(PhiNode phi) { - return gen.getLIRKind(phi.stamp()); + return gen.getLIRKind(phi.stamp(NodeView.DEFAULT)); } @Override @@ -529,13 +531,13 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - LIRKind kind = gen.getLIRKind(node.getValue().stamp()); + LIRKind kind = gen.getLIRKind(node.getValue().stamp(NodeView.DEFAULT)); Value nullValue = gen.emitConstant(kind, JavaConstant.NULL_POINTER); gen.emitCompareBranch(kind.getPlatformKind(), operand(node.getValue()), nullValue, Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability); } public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - PlatformKind kind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind(); + PlatformKind kind = gen.getLIRKind(compare.getX().stamp(NodeView.DEFAULT)).getPlatformKind(); gen.emitCompareBranch(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability); } @@ -558,12 +560,12 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) { if (node instanceof IsNullNode) { IsNullNode isNullNode = (IsNullNode) node; - LIRKind kind = gen.getLIRKind(isNullNode.getValue().stamp()); + LIRKind kind = gen.getLIRKind(isNullNode.getValue().stamp(NodeView.DEFAULT)); Value nullValue = gen.emitConstant(kind, JavaConstant.NULL_POINTER); return gen.emitConditionalMove(kind.getPlatformKind(), operand(isNullNode.getValue()), nullValue, Condition.EQ, false, trueValue, falseValue); } else if (node instanceof CompareNode) { CompareNode compare = (CompareNode) node; - PlatformKind kind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind(); + PlatformKind kind = gen.getLIRKind(compare.getX().stamp(NodeView.DEFAULT)).getPlatformKind(); return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); } else if (node instanceof LogicConstantNode) { return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue); @@ -579,7 +581,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio public void emitInvoke(Invoke x) { LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget(); FrameMapBuilder frameMapBuilder = gen.getResult().getFrameMapBuilder(); - CallingConvention invokeCc = frameMapBuilder.getRegisterConfig().getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(gen.getMetaAccess()), callTarget.signature(), gen); + CallingConvention invokeCc = frameMapBuilder.getRegisterConfig().getCallingConvention(callTarget.callType(), x.asNode().stamp(NodeView.DEFAULT).javaType(gen.getMetaAccess()), + callTarget.signature(), gen); frameMapBuilder.callsMethod(invokeCc); Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments()); @@ -650,7 +653,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio if (keyCount == 1) { assert defaultTarget != null; double probability = x.probability(x.keySuccessor(0)); - LIRKind kind = gen.getLIRKind(x.value().stamp()); + LIRKind kind = gen.getLIRKind(x.value().stamp(NodeView.DEFAULT)); Value key = gen.emitConstant(kind, x.keyAt(0)); gen.emitCompareBranch(kind.getPlatformKind(), gen.load(operand(x.value())), key, Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability); } else if (x instanceof IntegerSwitchNode && x.isSorted()) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/VersionsTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/VersionsTest.java new file mode 100644 index 00000000000..f9b562f0e21 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/VersionsTest.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2013, 2017, 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.graalvm.compiler.debug.test; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.HashMap; +import java.util.Map; +import org.graalvm.compiler.debug.Versions; +import org.junit.After; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; +import org.junit.Test; + +public class VersionsTest { + private File temporaryDirectory; + + @After + public void cleanUp() throws IOException { + if (temporaryDirectory != null) { + Files.walkFileTree(temporaryDirectory.toPath(), new FileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } + temporaryDirectory = null; + } + + @Test + public void emptyProperties() { + Path root = Paths.get("file:/"); + Versions v = new Versions(root); + assertEmpty(v.withVersions(null)); + } + + @Test + public void emptyWithNullProperties() { + Path root = Paths.get("file:/"); + Versions v = new Versions(root); + assertEmpty(v.withVersions(null)); + } + + @Test + public void readFromSameDirNullProps() throws IOException { + File dir = prepareReleaseFile(); + + Versions v = new Versions(dir.toPath()); + Map map = v.withVersions(null); + assertNonModifiable(map); + + assertEquals("16055f1ffaf736b7b86dcfaea53971983cd9ae0a", map.get("version.sdk")); + assertEquals("7930979c3b0af09a910accaaf3e73b2a55d2bade", map.get("version.truffleruby")); + } + + @Test + public void readFromSameDir() throws IOException { + File dir = prepareReleaseFile(); + + Versions v = new Versions(dir.toPath()); + + Map prepared = new HashMap<>(); + prepared.put("test", "best"); + + Map map = v.withVersions(prepared); + assertSame(prepared, map); + + assertEquals("16055f1ffaf736b7b86dcfaea53971983cd9ae0a", map.get("version.sdk")); + assertEquals("7930979c3b0af09a910accaaf3e73b2a55d2bade", map.get("version.truffleruby")); + assertEquals("best", map.get("test")); + } + + @Test + public void readFromSubDirNullProps() throws IOException { + File dir = prepareSubReleaseFile(); + + Versions v = new Versions(dir.toPath()); + Map map = v.withVersions(null); + assertNonModifiable(map); + + assertEquals("16055f1ffaf736b7b86dcfaea53971983cd9ae0a", map.get("version.sdk")); + assertEquals("7930979c3b0af09a910accaaf3e73b2a55d2bade", map.get("version.truffleruby")); + } + + @Test + public void readFromSubDir() throws IOException { + File dir = prepareSubReleaseFile(); + + Versions v = new Versions(dir.toPath()); + + Map prepared = new HashMap<>(); + prepared.put("test", "best"); + + Map map = v.withVersions(prepared); + assertSame(prepared, map); + + assertEquals("16055f1ffaf736b7b86dcfaea53971983cd9ae0a", map.get("version.sdk")); + assertEquals("7930979c3b0af09a910accaaf3e73b2a55d2bade", map.get("version.truffleruby")); + assertEquals("best", map.get("test")); + } + + private File prepareReleaseFile() throws IOException { + if (temporaryDirectory == null) { + temporaryDirectory = File.createTempFile("versions", ".tmp"); + temporaryDirectory.delete(); + assumeTrue(temporaryDirectory.mkdirs()); + try (FileWriter w = new FileWriter(new File(temporaryDirectory, "release"))) { +// @formatter:off + w.write( +"OS_NAME=linux\n" + +"OS_ARCH=amd64\n" + +"SOURCE=\" truffle:16055f1ffaf736b7b86dcfaea53971983cd9ae0a sdk:16055f1ffaf736b7b86dcfaea53971983cd9ae0a " + +"tools-enterprise:fcc1292a05e807a63589e24ce6073aafdef45bb9 graal-js:d374a8fd2733487a9f7518be6a55eb6163a779d1 " + +"graal-nodejs:3fcaf6874c9059d5ca5f0615edaa405d66cc1b02 truffleruby:7930979c3b0af09a910accaaf3e73b2a55d2bade " + +"fastr:079c6513b46f36abc24bce8aa6022c90576b3eaf graalpython:4cbee7853d460930c4d693970a21b73f811a4703 " + +"sulong:2c425f92caa004b12f60428a3e7e6e2715b51f87 substratevm:fcc1292a05e807a63589e24ce6073aafdef45bb9 " + +"compiler:16055f1ffaf736b7b86dcfaea53971983cd9ae0a substratevm-enterprise:fcc1292a05e807a63589e24ce6073aafdef45bb9 " + +"vm-enterprise:fcc1292a05e807a63589e24ce6073aafdef45bb9 graal-enterprise:fcc1292a05e807a63589e24ce6073aafdef45bb9 \"\n" + +"COMMIT_INFO={\"vm-enterprise\":{\"commit.rev\":\"fcc1292a05e807a63589e24ce6073aafdef45bb9\"," + +"\"commit.committer\":\"Vojin Jovanovic \",}}\n" + +"GRAALVM_VERSION=\"0.29-dev\"" + ); +// @formatter:on + } + } + return temporaryDirectory; + } + + private File prepareSubReleaseFile() throws IOException { + File subdir = new File(prepareReleaseFile(), "subdir"); + assumeTrue(subdir.mkdirs()); + return subdir; + } + + private static void assertEmpty(Map map) { + assertNotNull(map); + assertTrue(map.isEmpty()); + assertNonModifiable(map); + } + + private static void assertNonModifiable(Map map) { + try { + map.put(null, null); + fail("Map shall not be modifiable: " + map); + } catch (UnsupportedOperationException ex) { + // ok + } + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java index 96cd6cbf524..ae2285f019b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java @@ -129,6 +129,20 @@ public final class DebugContext implements AutoCloseable { } } + /** + * Adds version properties to the provided map. The version properties are read at a start of + * the JVM from a JVM specific location. Each property identifiers a commit of a certain + * component in the system. The properties added to the {@code properties} map are prefixed with + * {@code "version."} prefix. + * + * @param properties map to add the version properties to or {@code null} + * @return {@code properties} with version properties added or an unmodifiable map containing + * the version properties if {@code properties == null} + */ + public static Map addVersionProperties(Map properties) { + return Versions.VERSIONS.withVersions(properties); + } + /** * The immutable configuration that can be shared between {@link DebugContext} objects. */ diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Versions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Versions.java new file mode 100644 index 00000000000..6de0bfe3020 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Versions.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012, 2017, 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.graalvm.compiler.debug; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** Avoid using directly. Only public for the needs of unit testing. */ +public final class Versions { + static final Versions VERSIONS; + static { + String home = System.getProperty("java.home"); + VERSIONS = new Versions(home == null ? null : new File(home).toPath()); + } + + private final Map versions; + + public Versions(Path home) { + Map map = new HashMap<>(); + ASSIGN: try { + Path info = findReleaseInfo(home); + if (info == null) { + break ASSIGN; + } + for (String line : Files.readAllLines(info)) { + final String prefix = "SOURCE="; + if (line.startsWith(prefix)) { + for (String versionInfo : line.substring(prefix.length()).replace('"', ' ').split(" ")) { + String[] idVersion = versionInfo.split(":"); + if (idVersion != null && idVersion.length == 2) { + map.put("version." + idVersion[0], idVersion[1]); + } + } + break ASSIGN; + } + } + } catch (IOException ex) { + // no versions file found + } + versions = Collections.unmodifiableMap(map); + } + + public Map withVersions(Map properties) { + if (properties == null) { + return versions; + } else { + properties.putAll(versions); + return properties; + } + } + + private static Path findReleaseInfo(Path jreDir) { + if (jreDir == null) { + return null; + } + Path releaseInJre = jreDir.resolve("release"); + if (Files.exists(releaseInJre)) { + return releaseInJre; + } + Path jdkDir = jreDir.getParent(); + if (jdkDir == null) { + return null; + } + Path releaseInJdk = jdkDir.resolve("release"); + return Files.exists(releaseInJdk) ? releaseInJdk : null; + } + +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java index 79be3d65623..182f6f4c5bd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -37,10 +37,18 @@ import jdk.vm.ci.code.Register; abstract class AArch64HotSpotEpilogueOp extends AArch64BlockEndOp { private final GraalHotSpotVMConfig config; + private final Register thread; + + protected AArch64HotSpotEpilogueOp(LIRInstructionClass c, GraalHotSpotVMConfig config, Register thread) { + super(c); + this.config = config; + this.thread = thread; + } protected AArch64HotSpotEpilogueOp(LIRInstructionClass c, GraalHotSpotVMConfig config) { super(c); this.config = config; + this.thread = null; // no safepoint } protected void leaveFrame(CompilationResultBuilder crb, AArch64MacroAssembler masm, boolean emitSafepoint) { @@ -49,7 +57,7 @@ abstract class AArch64HotSpotEpilogueOp extends AArch64BlockEndOp { if (emitSafepoint) { try (ScratchRegister sc = masm.getScratchRegister()) { Register scratch = sc.getRegister(); - AArch64HotSpotSafepointOp.emitCode(crb, masm, config, true, scratch, null); + AArch64HotSpotSafepointOp.emitCode(crb, masm, config, true, thread, scratch, null); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java index 1803ea3adbb..2ed6e3408c0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -342,7 +342,8 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H operand = resultOperandFor(kind, input.getValueKind()); emitMove(operand, input); } - append(new AArch64HotSpotReturnOp(operand, getStub() != null, config)); + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new AArch64HotSpotReturnOp(operand, getStub() != null, config, thread)); } /** diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java index 7865e886a87..e67915192cb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,7 @@ import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.DirectCallTargetNode; import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.IndirectCallTargetNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -110,7 +111,7 @@ public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implemen for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { Value paramValue = params[param.index()]; - assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp())) : paramValue.getValueKind() + " != " + param.stamp(); + assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp(NodeView.DEFAULT))) : paramValue.getValueKind() + " != " + param.stamp(NodeView.DEFAULT); setResult(param, gen.emitMove(paramValue)); } } @@ -118,8 +119,9 @@ public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implemen @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(i); + Register thread = getGen().getProviders().getRegisters().getThreadRegister(); Variable scratch = gen.newVariable(LIRKind.value(getGen().target().arch.getWordKind())); - append(new AArch64HotSpotSafepointOp(info, getGen().config, scratch)); + append(new AArch64HotSpotSafepointOp(info, getGen().config, thread, scratch)); } @Override @@ -180,7 +182,7 @@ public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implemen public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; for (int i = 0; i < sig.length; i++) { - sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); + sig[i] = node.arguments().get(i).stamp(NodeView.DEFAULT).javaType(gen.getMetaAccess()); } Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java index 283e3fa7cf2..3065f491c6d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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,6 +33,7 @@ import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.Value; /** @@ -46,8 +47,8 @@ public final class AArch64HotSpotReturnOp extends AArch64HotSpotEpilogueOp { @Use({REG, ILLEGAL}) private Value result; private final boolean isStub; - public AArch64HotSpotReturnOp(Value result, boolean isStub, GraalHotSpotVMConfig config) { - super(TYPE, config); + public AArch64HotSpotReturnOp(Value result, boolean isStub, GraalHotSpotVMConfig config, Register thread) { + super(TYPE, config, thread); assert validReturnValue(result); this.result = result; this.isStub = isStub; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java index a2023faf776..f075f28bf8b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,18 +50,20 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction { @Temp protected AllocatableValue scratchValue; private final GraalHotSpotVMConfig config; + private final Register thread; - public AArch64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, AllocatableValue scratch) { + public AArch64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, Register thread, AllocatableValue scratch) { super(TYPE); this.state = state; this.config = config; + this.thread = thread; this.scratchValue = scratch; } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register scratch = asRegister(scratchValue); - emitCode(crb, masm, config, false, scratch, state); + emitCode(crb, masm, config, false, thread, scratch, state); } /** @@ -76,7 +78,15 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction { return !NumUtil.isSignedNbit(21, pollingPageAddress - config.codeCacheLowBound) || !NumUtil.isSignedNbit(21, pollingPageAddress - config.codeCacheHighBound); } - public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register scratch, LIRFrameState state) { + public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register thread, Register scratch, LIRFrameState state) { + if (config.threadLocalHandshakes) { + emitThreadLocalPoll(crb, masm, config, onReturn, thread, scratch, state); + } else { + emitGlobalPoll(crb, masm, config, onReturn, scratch, state); + } + } + + private static void emitGlobalPoll(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register scratch, LIRFrameState state) { if (isPollingPageFar(config)) { crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); masm.movNativeAddress(scratch, config.safepointPollingAddress); @@ -94,4 +104,15 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction { } } + private static void emitThreadLocalPoll(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register thread, Register scratch, + LIRFrameState state) { + assert config.threadPollingPageOffset >= 0; + masm.ldr(64, scratch, masm.makeAddress(thread, config.threadPollingPageOffset, 8)); + crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); + if (state != null) { + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); + } + masm.ldr(32, zr, AArch64Address.createBaseRegisterOnlyAddress(scratch)); + } + } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java index 4d1adff918e..6585e2135da 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; @@ -170,7 +171,7 @@ public class DataPatchInConstantsTest extends HotSpotGraalCompilerTest { @Input protected ValueNode input; protected LoadThroughPatchNode(ValueNode input) { - super(TYPE, input.stamp()); + super(TYPE, input.stamp(NodeView.DEFAULT)); this.input = input; } @@ -179,9 +180,9 @@ public class DataPatchInConstantsTest extends HotSpotGraalCompilerTest { assert input.isConstant(); LIRGeneratorTool gen = generator.getLIRGeneratorTool(); - Variable ret = gen.newVariable(gen.getLIRKind(stamp())); + Variable ret = gen.newVariable(gen.getLIRKind(stamp(NodeView.DEFAULT))); - gen.append(new LoadThroughPatchOp(input.asConstant(), stamp() instanceof NarrowOopStamp, ret)); + gen.append(new LoadThroughPatchOp(input.asConstant(), stamp(NodeView.DEFAULT) instanceof NarrowOopStamp, ret)); generator.setResult(this, ret); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java index 70bf4dae8c9..e2be3f3bb26 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java @@ -43,6 +43,7 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CompressionNode; import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; @@ -76,7 +77,7 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { @Override public void generate(NodeLIRBuilderTool generator) { - LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp()); + LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); generator.setResult(this, heapBaseRegister.asValue(kind)); } } @@ -117,11 +118,6 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { return false; } - @Override - protected boolean mightBeOptimized(ValueNode value) { - return super.mightBeOptimized(value) || value instanceof CompressionNode; - } - private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other, boolean isBaseNegated, boolean isIndexNegated) { if (isBaseNegated || isIndexNegated || compression.getOp() != CompressionOp.Uncompress) { return false; @@ -134,7 +130,7 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } if (heapBaseRegister != null && encoding.getBase() == heapBase) { - if ((!generatePIC || compression.stamp() instanceof ObjectStamp) && other == null) { + if ((!generatePIC || compression.stamp(NodeView.DEFAULT) instanceof ObjectStamp) && other == null) { // With PIC it is only legal to do for oops since the base value may be // different at runtime. ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister)); @@ -142,7 +138,7 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } else { return false; } - } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp() instanceof KlassPointerStamp)) { + } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp(NodeView.DEFAULT) instanceof KlassPointerStamp)) { if (generatePIC) { if (other == null) { ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index 3a26ff997a7..9082a2bc874 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -264,7 +264,8 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp if (pollOnReturnScratchRegister == null) { pollOnReturnScratchRegister = findPollOnReturnScratchRegister(); } - append(new AMD64HotSpotReturnOp(operand, getStub() != null, pollOnReturnScratchRegister, config)); + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new AMD64HotSpotReturnOp(operand, getStub() != null, thread, pollOnReturnScratchRegister, config)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java index 93a2c360fa8..7f71cac66ff 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.DirectCallTargetNode; import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.IndirectCallTargetNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -113,7 +114,7 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { Value paramValue = params[param.index()]; - assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp())) : paramValue.getValueKind() + " != " + param.stamp(); + assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp(NodeView.DEFAULT))) : paramValue.getValueKind() + " != " + param.stamp(NodeView.DEFAULT); setResult(param, gen.emitMove(paramValue)); } } @@ -121,7 +122,8 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(i); - append(new AMD64HotSpotSafepointOp(info, getGen().config, this)); + Register thread = getGen().getProviders().getRegisters().getThreadRegister(); + append(new AMD64HotSpotSafepointOp(info, getGen().config, this, thread)); } @Override @@ -186,7 +188,7 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; for (int i = 0; i < sig.length; i++) { - sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); + sig[i] = node.arguments().get(i).stamp(NodeView.DEFAULT).javaType(gen.getMetaAccess()); } Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java index ffcdc620df1..3428e278828 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,13 +45,15 @@ final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueBlockEndOp implemen public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotReturnOp.class); @Use({REG, ILLEGAL}) protected Value value; private final boolean isStub; + private final Register thread; private final Register scratchForSafepointOnReturn; private final GraalHotSpotVMConfig config; - AMD64HotSpotReturnOp(Value value, boolean isStub, Register scratchForSafepointOnReturn, GraalHotSpotVMConfig config) { + AMD64HotSpotReturnOp(Value value, boolean isStub, Register thread, Register scratchForSafepointOnReturn, GraalHotSpotVMConfig config) { super(TYPE); this.value = value; this.isStub = isStub; + this.thread = thread; this.scratchForSafepointOnReturn = scratchForSafepointOnReturn; this.config = config; } @@ -61,7 +63,7 @@ final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueBlockEndOp implemen leaveFrameAndRestoreRbp(crb, masm); if (!isStub) { // Every non-stub compile method must have a poll before the return. - AMD64HotSpotSafepointOp.emitCode(crb, masm, config, true, null, scratchForSafepointOnReturn); + AMD64HotSpotSafepointOp.emitCode(crb, masm, config, true, null, thread, scratchForSafepointOnReturn); /* * We potentially return to the interpreter, and that's an AVX-SSE transition. The only diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java index 7a5ee813a89..59ae1546014 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,12 +58,14 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { @Temp({OperandFlag.REG, OperandFlag.ILLEGAL}) private AllocatableValue temp; private final GraalHotSpotVMConfig config; + private final Register thread; - public AMD64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, NodeLIRBuilderTool tool) { + public AMD64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, NodeLIRBuilderTool tool, Register thread) { super(TYPE); this.state = state; this.config = config; - if (isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) { + this.thread = thread; + if (config.threadLocalHandshakes || isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) { temp = tool.getLIRGeneratorTool().newVariable(LIRKind.value(tool.getLIRGeneratorTool().target().arch.getWordKind())); } else { // Don't waste a register if it's unneeded @@ -73,7 +75,15 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) { - emitCode(crb, asm, config, false, state, temp instanceof RegisterValue ? ((RegisterValue) temp).getRegister() : null); + emitCode(crb, asm, config, false, state, thread, temp instanceof RegisterValue ? ((RegisterValue) temp).getRegister() : null); + } + + public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread, Register scratch) { + if (config.threadLocalHandshakes) { + emitThreadLocalPoll(crb, asm, config, atReturn, state, thread, scratch); + } else { + emitGlobalPoll(crb, asm, config, atReturn, state, scratch); + } } /** @@ -85,7 +95,7 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { return config.forceUnreachable || !isInt(pollingPageAddress - config.codeCacheLowBound) || !isInt(pollingPageAddress - config.codeCacheHighBound); } - public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { + private static void emitGlobalPoll(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { assert !atReturn || state == null : "state is unneeded at return"; if (ImmutableCode.getValue(crb.getOptions())) { JavaKind hostWordKind = JavaKind.Long; @@ -123,4 +133,18 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { asm.testl(rax, new AMD64Address(rip, 0)); } } + + private static void emitThreadLocalPoll(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread, + Register scratch) { + assert !atReturn || state == null : "state is unneeded at return"; + + assert config.threadPollingPageOffset >= 0; + asm.movptr(scratch, new AMD64Address(thread, config.threadPollingPageOffset)); + crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); + final int pos = asm.position(); + if (state != null) { + crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + } + asm.testl(rax, new AMD64Address(scratch)); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java index 883a91dd2fe..793935718a5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java @@ -190,7 +190,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp operand = resultOperandFor(javaKind, input.getValueKind()); emitMove(operand, input); } - append(new SPARCHotSpotReturnOp(operand, getStub() != null, config, getSafepointAddressValue())); + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new SPARCHotSpotReturnOp(operand, getStub() != null, config, thread, getSafepointAddressValue())); } @Override @@ -383,7 +384,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp public AllocatableValue getSafepointAddressValue() { if (this.safepointAddressValue == null) { - this.safepointAddressValue = newVariable(LIRKind.value(target().arch.getWordKind())); + this.safepointAddressValue = SPARCHotSpotSafepointOp.getSafepointAddressValue(this); } return this.safepointAddressValue; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java index 09dc9cf5f42..afe79ed1132 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.DirectCallTargetNode; import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.IndirectCallTargetNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -84,7 +85,8 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(i); - append(new SPARCHotSpotSafepointOp(info, getGen().config, gen)); + Register thread = getGen().getProviders().getRegisters().getThreadRegister(); + append(new SPARCHotSpotSafepointOp(info, getGen().config, thread, gen)); } @Override @@ -141,9 +143,7 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H @Override protected void emitPrologue(StructuredGraph graph) { super.emitPrologue(graph); - AllocatableValue var = getGen().getSafepointAddressValue(); - append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, getGen().config)); - getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); + SPARCHotSpotSafepointOp.emitPrologue(this, getGen()); } @Override @@ -159,7 +159,7 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; for (int i = 0; i < sig.length; i++) { - sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); + sig[i] = node.arguments().get(i).stamp(NodeView.DEFAULT).javaType(gen.getMetaAccess()); } Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java index 134da9043f8..f27d72fd136 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -24,7 +24,6 @@ package org.graalvm.compiler.hotspot.sparc; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -33,6 +32,7 @@ import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.sparc.SPARCControlFlow.ReturnOp; +import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.Value; /** @@ -44,15 +44,17 @@ final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp { public static final SizeEstimate SIZE = SizeEstimate.create(2); @Use({REG, ILLEGAL}) protected Value value; - @Use({REG}) protected Value safepointPollAddress; + @Use({REG, ILLEGAL}) protected Value safepointPollAddress; private final boolean isStub; private final GraalHotSpotVMConfig config; + private final Register thread; - SPARCHotSpotReturnOp(Value value, boolean isStub, GraalHotSpotVMConfig config, Value safepointPoll) { + SPARCHotSpotReturnOp(Value value, boolean isStub, GraalHotSpotVMConfig config, Register thread, Value safepointPoll) { super(TYPE, SIZE); this.value = value; this.isStub = isStub; this.config = config; + this.thread = thread; this.safepointPollAddress = safepointPoll; } @@ -60,7 +62,7 @@ final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp { public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { if (!isStub) { // Every non-stub compile method must have a poll before the return. - SPARCHotSpotSafepointOp.emitCode(crb, masm, config, true, null, asRegister(safepointPollAddress)); + SPARCHotSpotSafepointOp.emitCode(crb, masm, config, true, null, thread, safepointPollAddress); } ReturnOp.emitCodeHelper(crb, masm); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotSafepointOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotSafepointOp.java index 4b0bf193314..b50dabf883e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotSafepointOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotSafepointOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,10 @@ import static jdk.vm.ci.sparc.SPARC.g0; import org.graalvm.compiler.asm.sparc.SPARCAddress; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; +import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister; +import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; @@ -39,6 +42,7 @@ import jdk.vm.ci.code.Register; import jdk.vm.ci.code.ValueUtil; import jdk.vm.ci.code.site.InfopointReason; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; /** * Emits a safepoint poll. @@ -49,23 +53,37 @@ public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction { public static final SizeEstimate SIZE = SizeEstimate.create(9); @State protected LIRFrameState state; - @Use({OperandFlag.REG}) AllocatableValue safepointPollAddress; + @Use({OperandFlag.REG, OperandFlag.ILLEGAL}) AllocatableValue safepointPollAddress; private final GraalHotSpotVMConfig config; + private final Register thread; - public SPARCHotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, LIRGeneratorTool tool) { + public SPARCHotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, Register thread, LIRGeneratorTool tool) { super(TYPE, SIZE); this.state = state; this.config = config; + this.thread = thread; SPARCHotSpotLIRGenerator lirGen = (SPARCHotSpotLIRGenerator) tool; safepointPollAddress = lirGen.getSafepointAddressValue(); } @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - emitCode(crb, masm, config, false, state, asRegister(safepointPollAddress)); + emitCode(crb, masm, config, false, state, thread, safepointPollAddress); } - public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register safepointPollAddress) { + public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread, + Value safepointPollAddress) { + if (config.threadLocalHandshakes) { + emitThreadLocalPoll(crb, masm, config, atReturn, state, thread); + } else { + emitGlobalPoll(crb, masm, config, atReturn, state, asRegister(safepointPollAddress)); + } + } + + /** + * Emit a global safepoint poll. + */ + private static void emitGlobalPoll(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register safepointPollAddress) { crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); if (state != null) { final int pos = masm.position(); @@ -74,6 +92,44 @@ public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction { masm.ldx(new SPARCAddress(safepointPollAddress, 0), g0); } + /** + * Emit a thread-local safepoint poll. + */ + private static void emitThreadLocalPoll(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread) { + assert !atReturn || state == null : "state is unneeded at return"; + + assert config.threadPollingPageOffset >= 0; + + try (ScratchRegister scratchReg = masm.getScratchRegister()) { + Register scratch = scratchReg.getRegister(); + + masm.ldx(new SPARCAddress(thread, config.threadPollingPageOffset), scratch); + + crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); + if (state != null) { + final int pos = masm.position(); + crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + } + masm.ldx(new SPARCAddress(scratch, 0), g0); + } + } + + static AllocatableValue getSafepointAddressValue(SPARCHotSpotLIRGenerator gen) { + if (gen.config.threadLocalHandshakes) { + return Value.ILLEGAL; + } else { + return gen.newVariable(LIRKind.value(gen.target().arch.getWordKind())); + } + } + + static void emitPrologue(SPARCHotSpotNodeLIRBuilder lir, SPARCHotSpotLIRGenerator gen) { + if (!gen.config.threadLocalHandshakes) { + AllocatableValue var = gen.getSafepointAddressValue(); + lir.append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, gen.config)); + gen.append(((HotSpotDebugInfoBuilder) lir.getDebugInfoBuilder()).lockStack()); + } + } + public static class SPARCLoadSafepointPollAddress extends SPARCLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCLoadSafepointPollAddress.class); public static final SizeEstimate SIZE = SizeEstimate.create(2); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java index a08edd079c0..bd0c8693723 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java @@ -22,14 +22,15 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; - +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -41,10 +42,8 @@ import org.junit.Assume; import org.junit.Before; import org.junit.Test; -import jdk.vm.ci.aarch64.AArch64; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; +import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; +import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; /** * use @@ -55,7 +54,7 @@ import jdk.vm.ci.meta.JavaKind; * * to print disassembly. */ -public class AheadOfTimeCompilationTest extends GraalCompilerTest { +public class AheadOfTimeCompilationTest extends HotSpotGraalCompilerTest { public static final Object STATICFINALOBJECT = new Object(); public static final String STATICFINALSTRING = "test string"; @@ -74,9 +73,10 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { public void testStaticFinalObjectAOT() { StructuredGraph result = compile("getStaticFinalObject", true); assertDeepEquals(1, getConstantNodes(result).count()); - Stamp constantStamp = getConstantNodes(result).first().stamp(); + Stamp constantStamp = getConstantNodes(result).first().stamp(NodeView.DEFAULT); Assert.assertTrue(constantStamp.toString(), constantStamp instanceof KlassPointerStamp); - assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); + int expected = runtime().getVMConfig().classMirrorIsHandle ? 3 : 2; + assertDeepEquals(expected, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -99,8 +99,8 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { assertDeepEquals(1, filter.count()); HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(AheadOfTimeCompilationTest.class); assertDeepEquals(type.klass(), filter.first().asConstant()); - - assertDeepEquals(1, result.getNodes().filter(ReadNode.class).count()); + int expected = runtime().getVMConfig().classMirrorIsHandle ? 2 : 1; + assertDeepEquals(expected, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -124,10 +124,10 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { StructuredGraph result = compile("getPrimitiveClassObject", true); NodeIterable filter = getConstantNodes(result); assertDeepEquals(1, filter.count()); - Stamp constantStamp = filter.first().stamp(); + Stamp constantStamp = filter.first().stamp(NodeView.DEFAULT); Assert.assertTrue(constantStamp instanceof KlassPointerStamp); - - assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); + int expected = runtime().getVMConfig().classMirrorIsHandle ? 3 : 2; + assertDeepEquals(expected, result.getNodes().filter(ReadNode.class).count()); } @Test diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index 8363e827907..8802c18dc3f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -143,50 +143,49 @@ public class CheckGraalIntrinsics extends GraalTest { } static { + // These are dead add(IGNORE, - // dead "java/lang/Math.atan2(DD)D", - // Used during stack walking - "java/lang/Throwable.fillInStackTrace()Ljava/lang/Throwable;", - // Marker intrinsic id - "java/lang/invoke/MethodHandle.*", - // Marker intrinsic id - "java/lang/invoke/MethodHandle.invoke*", - // Implemented through lowering - "java/lang/ref/Reference.get()Ljava/lang/Object;", - // Used during stack walk - "java/lang/reflect/Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", - // Only used by C1 - "java/nio/Buffer.checkIndex(I)I", - // dead + "jdk/internal/misc/Unsafe.park(ZJ)V", + "jdk/internal/misc/Unsafe.unpark(Ljava/lang/Object;)V", "sun/misc/Unsafe.park(ZJ)V", - // dead "sun/misc/Unsafe.prefetchRead(Ljava/lang/Object;J)V", - // dead "sun/misc/Unsafe.prefetchReadStatic(Ljava/lang/Object;J)V", - // dead "sun/misc/Unsafe.prefetchWrite(Ljava/lang/Object;J)V", - // dead "sun/misc/Unsafe.prefetchWriteStatic(Ljava/lang/Object;J)V", - // dead "sun/misc/Unsafe.unpark(Ljava/lang/Object;)V"); - add(TO_BE_INVESTIGATED, - // JDK 8 - "java/lang/Double.doubleToLongBits(D)J", - "java/lang/Float.floatToIntBits(F)I", - "java/lang/Integer.toString(I)Ljava/lang/String;", - "java/lang/Math.decrementExact(I)I", - "java/lang/Math.decrementExact(J)J", - "java/lang/Math.incrementExact(I)I", - "java/lang/Math.incrementExact(J)J", + // These only exist to assist escape analysis in C2 + add(IGNORE, + "java/lang/Throwable.fillInStackTrace()Ljava/lang/Throwable;"); + + // These are only used for the security handling during stack walking + add(IGNORE, + "java/lang/reflect/Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); + + // These are marker intrinsic ids only + add(IGNORE, + "java/lang/invoke/MethodHandle.*", + "java/lang/invoke/MethodHandle.invoke*"); + + // These are implemented through lowering + add(IGNORE, + "java/lang/ref/Reference.get()Ljava/lang/Object;"); + + // These are only used by C1 + add(IGNORE, + "java/nio/Buffer.checkIndex(I)I"); + + // These do general compiler optimizations and convert min/max to cmov instructions. We are + // ignoring them as cmovs are not necessarily beneficial. + add(IGNORE, "java/lang/Math.max(II)I", - "java/lang/Math.min(II)I", - "java/lang/Math.negateExact(I)I", - "java/lang/Math.negateExact(J)J", + "java/lang/Math.min(II)I"); + + // These are known to be implemented down stream + add(IGNORE, + "java/lang/Integer.toString(I)Ljava/lang/String;", "java/lang/String.(Ljava/lang/String;)V", - "java/lang/String.compareTo(Ljava/lang/String;)I", - "java/lang/String.indexOf(Ljava/lang/String;)I", "java/lang/StringBuffer.()V", "java/lang/StringBuffer.(I)V", "java/lang/StringBuffer.(Ljava/lang/String;)V", @@ -201,172 +200,11 @@ public class CheckGraalIntrinsics extends GraalTest { "java/lang/StringBuilder.append(I)Ljava/lang/StringBuilder;", "java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;", "java/lang/StringBuilder.toString()Ljava/lang/String;", - "java/lang/reflect/Array.newArray(Ljava/lang/Class;I)Ljava/lang/Object;", "java/util/Arrays.copyOf([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;", - "java/util/Arrays.copyOfRange([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;", - "oracle/jrockit/jfr/Timing.counterTime()J", - "oracle/jrockit/jfr/VMJFR.classID0(Ljava/lang/Class;)J", - "oracle/jrockit/jfr/VMJFR.threadID()I", - "sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I", - "sun/security/provider/DigestBase.implCompressMultiBlock([BII)I", - "sun/security/provider/SHA.implCompress([BI)V", - "sun/security/provider/SHA2.implCompress([BI)V", - "sun/security/provider/SHA5.implCompress([BI)V"); + "java/util/Arrays.copyOfRange([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;"); - add(TO_BE_INVESTIGATED, - // JDK 9 - "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I", - "com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V", - "java/lang/Math.fma(DDD)D", - "java/lang/Math.fma(FFF)F", - "java/lang/Object.notify()V", - "java/lang/Object.notifyAll()V", - "java/lang/StringCoding.hasNegatives([BII)Z", - "java/lang/StringCoding.implEncodeISOArray([BI[BII)I", - "java/lang/StringLatin1.compareTo([B[B)I", - "java/lang/StringLatin1.compareToUTF16([B[B)I", - "java/lang/StringLatin1.equals([B[B)Z", - "java/lang/StringLatin1.indexOf([BI[BII)I", - "java/lang/StringLatin1.indexOf([B[B)I", - "java/lang/StringLatin1.inflate([BI[BII)V", - "java/lang/StringLatin1.inflate([BI[CII)V", - "java/lang/StringUTF16.compareTo([B[B)I", - "java/lang/StringUTF16.compareToLatin1([B[B)I", - "java/lang/StringUTF16.compress([BI[BII)I", - "java/lang/StringUTF16.compress([CI[BII)I", - "java/lang/StringUTF16.equals([B[B)Z", - "java/lang/StringUTF16.getChar([BI)C", - "java/lang/StringUTF16.getChars([BII[CI)V", - "java/lang/StringUTF16.indexOf([BI[BII)I", - "java/lang/StringUTF16.indexOf([B[B)I", - "java/lang/StringUTF16.indexOfChar([BIII)I", - "java/lang/StringUTF16.indexOfLatin1([BI[BII)I", - "java/lang/StringUTF16.indexOfLatin1([B[B)I", - "java/lang/StringUTF16.putChar([BII)V", - "java/lang/StringUTF16.toBytes([CII)[B", - "java/lang/Thread.onSpinWait()V", - "java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z", - "java/math/BigInteger.implMontgomeryMultiply([I[I[IIJ[I)[I", - "java/math/BigInteger.implMontgomerySquare([I[IIJ[I)[I", - "java/math/BigInteger.implMulAdd([I[IIII)I", - "java/math/BigInteger.implSquareToLen([II[II)[I", - "java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I", - "java/util/stream/Streams$RangeIntSpliterator.forEachRemaining(Ljava/util/function/IntConsumer;)V", - "java/util/zip/Adler32.updateByteBuffer(IJII)I", - "java/util/zip/Adler32.updateBytes(I[BII)I", - "jdk/internal/misc/Unsafe.allocateUninitializedArray0(Ljava/lang/Class;I)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B", - "jdk/internal/misc/Unsafe.compareAndExchangeByteAcquire(Ljava/lang/Object;JBB)B", - "jdk/internal/misc/Unsafe.compareAndExchangeByteRelease(Ljava/lang/Object;JBB)B", - "jdk/internal/misc/Unsafe.compareAndExchangeInt(Ljava/lang/Object;JII)I", - "jdk/internal/misc/Unsafe.compareAndExchangeIntAcquire(Ljava/lang/Object;JII)I", - "jdk/internal/misc/Unsafe.compareAndExchangeIntRelease(Ljava/lang/Object;JII)I", - "jdk/internal/misc/Unsafe.compareAndExchangeLong(Ljava/lang/Object;JJJ)J", - "jdk/internal/misc/Unsafe.compareAndExchangeLongAcquire(Ljava/lang/Object;JJJ)J", - "jdk/internal/misc/Unsafe.compareAndExchangeLongRelease(Ljava/lang/Object;JJJ)J", - "jdk/internal/misc/Unsafe.compareAndExchangeObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.compareAndExchangeObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.compareAndExchangeObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S", - "jdk/internal/misc/Unsafe.compareAndExchangeShortAcquire(Ljava/lang/Object;JSS)S", - "jdk/internal/misc/Unsafe.compareAndExchangeShortRelease(Ljava/lang/Object;JSS)S", - "jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.compareAndSetShort(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.getAndAddByte(Ljava/lang/Object;JB)B", - "jdk/internal/misc/Unsafe.getAndAddShort(Ljava/lang/Object;JS)S", - "jdk/internal/misc/Unsafe.getAndSetByte(Ljava/lang/Object;JB)B", - "jdk/internal/misc/Unsafe.getAndSetShort(Ljava/lang/Object;JS)S", - "jdk/internal/misc/Unsafe.getBooleanAcquire(Ljava/lang/Object;J)Z", - "jdk/internal/misc/Unsafe.getBooleanOpaque(Ljava/lang/Object;J)Z", - "jdk/internal/misc/Unsafe.getByteAcquire(Ljava/lang/Object;J)B", - "jdk/internal/misc/Unsafe.getByteOpaque(Ljava/lang/Object;J)B", - "jdk/internal/misc/Unsafe.getCharAcquire(Ljava/lang/Object;J)C", - "jdk/internal/misc/Unsafe.getCharOpaque(Ljava/lang/Object;J)C", - "jdk/internal/misc/Unsafe.getDoubleAcquire(Ljava/lang/Object;J)D", - "jdk/internal/misc/Unsafe.getDoubleOpaque(Ljava/lang/Object;J)D", - "jdk/internal/misc/Unsafe.getFloatAcquire(Ljava/lang/Object;J)F", - "jdk/internal/misc/Unsafe.getFloatOpaque(Ljava/lang/Object;J)F", - "jdk/internal/misc/Unsafe.getIntAcquire(Ljava/lang/Object;J)I", - "jdk/internal/misc/Unsafe.getIntOpaque(Ljava/lang/Object;J)I", - "jdk/internal/misc/Unsafe.getLongAcquire(Ljava/lang/Object;J)J", - "jdk/internal/misc/Unsafe.getLongOpaque(Ljava/lang/Object;J)J", - "jdk/internal/misc/Unsafe.getObjectAcquire(Ljava/lang/Object;J)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.getObjectOpaque(Ljava/lang/Object;J)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.getShortAcquire(Ljava/lang/Object;J)S", - "jdk/internal/misc/Unsafe.getShortOpaque(Ljava/lang/Object;J)S", - "jdk/internal/misc/Unsafe.park(ZJ)V", - "jdk/internal/misc/Unsafe.putBooleanOpaque(Ljava/lang/Object;JZ)V", - "jdk/internal/misc/Unsafe.putByteOpaque(Ljava/lang/Object;JB)V", - "jdk/internal/misc/Unsafe.putCharOpaque(Ljava/lang/Object;JC)V", - "jdk/internal/misc/Unsafe.putDoubleOpaque(Ljava/lang/Object;JD)V", - "jdk/internal/misc/Unsafe.putFloatOpaque(Ljava/lang/Object;JF)V", - "jdk/internal/misc/Unsafe.putIntOpaque(Ljava/lang/Object;JI)V", - "jdk/internal/misc/Unsafe.putLongOpaque(Ljava/lang/Object;JJ)V", - "jdk/internal/misc/Unsafe.putObjectOpaque(Ljava/lang/Object;JLjava/lang/Object;)V", - "jdk/internal/misc/Unsafe.putShortOpaque(Ljava/lang/Object;JS)V", - "jdk/internal/misc/Unsafe.unpark(Ljava/lang/Object;)V", - "jdk/internal/misc/Unsafe.weakCompareAndSetByte(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetByteAcquire(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetBytePlain(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetByteRelease(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetInt(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntAcquire(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntPlain(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntRelease(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLong(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongAcquire(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongPlain(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongRelease(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectPlain(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShort(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortAcquire(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortPlain(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortRelease(Ljava/lang/Object;JSS)Z", - "jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I", - "jdk/jfr/internal/JVM.counterTime()J", - "jdk/jfr/internal/JVM.getBufferWriter()Ljava/lang/Object;", - "jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J", - "sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I", - "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I", - "sun/security/provider/SHA.implCompress0([BI)V", - "sun/security/provider/SHA2.implCompress0([BI)V", - "sun/security/provider/SHA5.implCompress0([BI)V"); - - if (!getHostArchitectureName().equals("amd64")) { - add(TO_BE_INVESTIGATED, - // Can we implement these on non-AMD64 platforms? C2 seems to. - "sun/misc/Unsafe.getAndAddInt(Ljava/lang/Object;JI)I", - "sun/misc/Unsafe.getAndAddLong(Ljava/lang/Object;JJ)J", - "sun/misc/Unsafe.getAndSetInt(Ljava/lang/Object;JI)I", - "sun/misc/Unsafe.getAndSetLong(Ljava/lang/Object;JJ)J", - "sun/misc/Unsafe.getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;"); - // JDK 9 - add(TO_BE_INVESTIGATED, - "jdk/internal/misc/Unsafe.getAndAddInt(Ljava/lang/Object;JI)I", - "jdk/internal/misc/Unsafe.getAndAddLong(Ljava/lang/Object;JJ)J", - "jdk/internal/misc/Unsafe.getAndSetInt(Ljava/lang/Object;JI)I", - "jdk/internal/misc/Unsafe.getAndSetLong(Ljava/lang/Object;JJ)J", - "jdk/internal/misc/Unsafe.getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C", - "jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I", - "jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J", - "jdk/internal/misc/Unsafe.getShortUnaligned(Ljava/lang/Object;J)S", - "jdk/internal/misc/Unsafe.putCharUnaligned(Ljava/lang/Object;JC)V", - "jdk/internal/misc/Unsafe.putIntUnaligned(Ljava/lang/Object;JI)V", - "jdk/internal/misc/Unsafe.putLongUnaligned(Ljava/lang/Object;JJ)V", - "jdk/internal/misc/Unsafe.putShortUnaligned(Ljava/lang/Object;JS)V"); - } - - HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); - GraalHotSpotVMConfig config = rt.getVMConfig(); - - /* - * These are known to be implemented but the platform dependent conditions for when they are - * enabled are complex so just ignore them all the time. - */ + // These are known to be implemented but the platform dependent conditions + // for when they are enabled are complex so just ignore them all the time. add(IGNORE, "java/lang/Integer.bitCount(I)I", "java/lang/Integer.numberOfLeadingZeros(I)I", @@ -375,52 +213,323 @@ public class CheckGraalIntrinsics extends GraalTest { "java/lang/Long.numberOfLeadingZeros(J)I", "java/lang/Long.numberOfTrailingZeros(J)I"); - if (!config.useCRC32Intrinsics) { - // Registration of the CRC32 plugins is guarded by UseCRC32Intrinsics - add(IGNORE, "java/util/zip/CRC32.update(II)I"); - if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { - add(IGNORE, - "java/util/zip/CRC32.updateByteBuffer(IJII)I", - "java/util/zip/CRC32.updateBytes(I[BII)I"); - } else { - add(IGNORE, - "java/util/zip/CRC32.updateByteBuffer0(IJII)I", - "java/util/zip/CRC32.updateBytes0(I[BII)I", - "java/util/zip/CRC32C.updateBytes(I[BII)I", - "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I"); - } - } else { - if (JDK9Method.JAVA_SPECIFICATION_VERSION >= 9) { + // Relevant for Java flight recorder + add(TO_BE_INVESTIGATED, + "oracle/jrockit/jfr/Timing.counterTime()J", + "oracle/jrockit/jfr/VMJFR.classID0(Ljava/lang/Class;)J", + "oracle/jrockit/jfr/VMJFR.threadID()I"); + + add(TO_BE_INVESTIGATED, + // Should be fairly easy to implement - C2 intrinsifies these to use "v != + // v" to check for NaN instead of looking at the bit pattern. + "java/lang/Double.doubleToLongBits(D)J", + "java/lang/Float.floatToIntBits(F)I", + + // Should be trivial to implement because we already have existing nodes + "java/lang/Math.decrementExact(I)I", + "java/lang/Math.decrementExact(J)J", + "java/lang/Math.incrementExact(I)I", + "java/lang/Math.incrementExact(J)J", + + // Similar to addExact + "java/lang/Math.negateExact(I)I", + // Similar to addExact + "java/lang/Math.negateExact(J)J", + // HotSpot MacroAssembler-based intrinsic + "java/lang/String.compareTo(Ljava/lang/String;)I", + // HotSpot MacroAssembler-based intrinsic + "java/lang/String.indexOf(Ljava/lang/String;)I", + // Can share most implementation parts with with + // Unsafe.allocateUninitializedArray0 + "java/lang/reflect/Array.newArray(Ljava/lang/Class;I)Ljava/lang/Object;", + // HotSpot MacroAssembler-based intrinsic + "sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I", + // Stub based intrinsics but implementation seems complex in C2 + "sun/security/provider/DigestBase.implCompressMultiBlock([BII)I"); + + if (isJDK9OrHigher()) { + // Relevant for Java flight recorder + add(TO_BE_INVESTIGATED, + "jdk/jfr/internal/JVM.counterTime()J", + "jdk/jfr/internal/JVM.getBufferWriter()Ljava/lang/Object;", + "jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J"); + + add(TO_BE_INVESTIGATED, + // Some logic and a stub call + "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I", + // Stub and very little logic + "com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V", + // HotSpot MacroAssembler-based intrinsic + "java/lang/Math.fma(DDD)D", + // HotSpot MacroAssembler-based intrinsic + "java/lang/Math.fma(FFF)F", + // Just a runtime call (the called C code has a better fast path) + "java/lang/Object.notify()V", + // Just a runtime call (the called C code has a better fast path) + "java/lang/Object.notifyAll()V", + // Emit pause instruction if os::is_MP() + "java/lang/Thread.onSpinWait()V", + // Just check if the argument is a compile time constant + "java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z", + // Some logic and a runtime call + "java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I", + // Only used as a marker for vectorization? + "java/util/stream/Streams$RangeIntSpliterator.forEachRemaining(Ljava/util/function/IntConsumer;)V", + // Only implemented on non-AMD64 platforms (some logic and runtime call) + "java/util/zip/Adler32.updateByteBuffer(IJII)I", + // Only implemented on non-AMD64 platforms (some logic and runtime call) + "java/util/zip/Adler32.updateBytes(I[BII)I", + // similar to CRC32.updateBytes + "java/util/zip/CRC32C.updateBytes(I[BII)I", + // similar to CRC32.updateDirectByteBuffer + "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I", + // Emits a slow and a fast path and some dispatching logic + "jdk/internal/misc/Unsafe.allocateUninitializedArray0(Ljava/lang/Class;I)Ljava/lang/Object;", + + // Should be easy to implement as it seems to match the logic that is + // already implemented in ValueCompareAndSwapNode. On the high-level, we + // would need something similar to UnsafeCompareAndSwapNode but with a + // different result type. + "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B", + "jdk/internal/misc/Unsafe.compareAndExchangeInt(Ljava/lang/Object;JII)I", + "jdk/internal/misc/Unsafe.compareAndExchangeLong(Ljava/lang/Object;JJJ)J", + "jdk/internal/misc/Unsafe.compareAndExchangeObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S", + + // Should be easy to implement as we already have an implementation for + // int, long, and Object. + "jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.compareAndSetShort(Ljava/lang/Object;JSS)Z", + + // Should be easy to implement as we already have an implementation for + // int and long. + "jdk/internal/misc/Unsafe.getAndAddByte(Ljava/lang/Object;JB)B", + "jdk/internal/misc/Unsafe.getAndAddShort(Ljava/lang/Object;JS)S", + + // Should be easy to implement as we already have an implementation for + // int, long, and Object. + "jdk/internal/misc/Unsafe.getAndSetByte(Ljava/lang/Object;JB)B", + "jdk/internal/misc/Unsafe.getAndSetShort(Ljava/lang/Object;JS)S", + + // Control flow, deopts, and a cast + "jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I", + // HotSpot MacroAssembler-based intrinsic + "sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I", + // Runtime call and some complex compiler logic + "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I"); + /* + * Per default, all these operations are mapped to some generic method for which we + * already have compiler intrinsics. Performance-wise it would be better to support them + * explicitly as the more generic method might be more restrictive and therefore slower + * than necessary. + */ + add(TO_BE_INVESTIGATED, + // Mapped to compareAndExchange* + "jdk/internal/misc/Unsafe.compareAndExchangeByteAcquire(Ljava/lang/Object;JBB)B", + "jdk/internal/misc/Unsafe.compareAndExchangeByteRelease(Ljava/lang/Object;JBB)B", + "jdk/internal/misc/Unsafe.compareAndExchangeIntAcquire(Ljava/lang/Object;JII)I", + "jdk/internal/misc/Unsafe.compareAndExchangeIntRelease(Ljava/lang/Object;JII)I", + "jdk/internal/misc/Unsafe.compareAndExchangeLongAcquire(Ljava/lang/Object;JJJ)J", + "jdk/internal/misc/Unsafe.compareAndExchangeLongRelease(Ljava/lang/Object;JJJ)J", + "jdk/internal/misc/Unsafe.compareAndExchangeObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.compareAndExchangeObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.compareAndExchangeShortAcquire(Ljava/lang/Object;JSS)S", + "jdk/internal/misc/Unsafe.compareAndExchangeShortRelease(Ljava/lang/Object;JSS)S", + + // Mapped to get*Volatile + "jdk/internal/misc/Unsafe.getBooleanAcquire(Ljava/lang/Object;J)Z", + "jdk/internal/misc/Unsafe.getBooleanOpaque(Ljava/lang/Object;J)Z", + "jdk/internal/misc/Unsafe.getByteAcquire(Ljava/lang/Object;J)B", + "jdk/internal/misc/Unsafe.getByteOpaque(Ljava/lang/Object;J)B", + "jdk/internal/misc/Unsafe.getCharAcquire(Ljava/lang/Object;J)C", + "jdk/internal/misc/Unsafe.getCharOpaque(Ljava/lang/Object;J)C", + "jdk/internal/misc/Unsafe.getDoubleAcquire(Ljava/lang/Object;J)D", + "jdk/internal/misc/Unsafe.getDoubleOpaque(Ljava/lang/Object;J)D", + "jdk/internal/misc/Unsafe.getFloatAcquire(Ljava/lang/Object;J)F", + "jdk/internal/misc/Unsafe.getFloatOpaque(Ljava/lang/Object;J)F", + "jdk/internal/misc/Unsafe.getIntAcquire(Ljava/lang/Object;J)I", + "jdk/internal/misc/Unsafe.getIntOpaque(Ljava/lang/Object;J)I", + "jdk/internal/misc/Unsafe.getLongAcquire(Ljava/lang/Object;J)J", + "jdk/internal/misc/Unsafe.getLongOpaque(Ljava/lang/Object;J)J", + "jdk/internal/misc/Unsafe.getObjectAcquire(Ljava/lang/Object;J)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.getObjectOpaque(Ljava/lang/Object;J)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.getShortAcquire(Ljava/lang/Object;J)S", + "jdk/internal/misc/Unsafe.getShortOpaque(Ljava/lang/Object;J)S", + + // Mapped to put*Volatile + "jdk/internal/misc/Unsafe.putBooleanOpaque(Ljava/lang/Object;JZ)V", + "jdk/internal/misc/Unsafe.putByteOpaque(Ljava/lang/Object;JB)V", + "jdk/internal/misc/Unsafe.putCharOpaque(Ljava/lang/Object;JC)V", + "jdk/internal/misc/Unsafe.putDoubleOpaque(Ljava/lang/Object;JD)V", + "jdk/internal/misc/Unsafe.putFloatOpaque(Ljava/lang/Object;JF)V", + "jdk/internal/misc/Unsafe.putIntOpaque(Ljava/lang/Object;JI)V", + "jdk/internal/misc/Unsafe.putLongOpaque(Ljava/lang/Object;JJ)V", + "jdk/internal/misc/Unsafe.putObjectOpaque(Ljava/lang/Object;JLjava/lang/Object;)V", + "jdk/internal/misc/Unsafe.putShortOpaque(Ljava/lang/Object;JS)V", + + // Mapped to compareAndSet* + "jdk/internal/misc/Unsafe.weakCompareAndSetByte(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetByteAcquire(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetBytePlain(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetByteRelease(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetInt(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetIntAcquire(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetIntPlain(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetIntRelease(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetLong(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetLongAcquire(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetLongPlain(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetLongRelease(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetObjectPlain(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetShort(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetShortAcquire(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetShortPlain(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetShortRelease(Ljava/lang/Object;JSS)Z"); + + // Compact string support - HotSpot MacroAssembler-based intrinsic or complex C2 logic. + add(TO_BE_INVESTIGATED, + "java/lang/StringCoding.hasNegatives([BII)Z", + "java/lang/StringCoding.implEncodeISOArray([BI[BII)I", + "java/lang/StringLatin1.compareTo([B[B)I", + "java/lang/StringLatin1.compareToUTF16([B[B)I", + "java/lang/StringLatin1.equals([B[B)Z", + "java/lang/StringLatin1.indexOf([BI[BII)I", + "java/lang/StringLatin1.indexOf([B[B)I", + "java/lang/StringLatin1.inflate([BI[BII)V", + "java/lang/StringLatin1.inflate([BI[CII)V", + "java/lang/StringUTF16.compareTo([B[B)I", + "java/lang/StringUTF16.compareToLatin1([B[B)I", + "java/lang/StringUTF16.compress([BI[BII)I", + "java/lang/StringUTF16.compress([CI[BII)I", + "java/lang/StringUTF16.equals([B[B)Z", + "java/lang/StringUTF16.getChar([BI)C", + "java/lang/StringUTF16.getChars([BII[CI)V", + "java/lang/StringUTF16.indexOf([BI[BII)I", + "java/lang/StringUTF16.indexOf([B[B)I", + "java/lang/StringUTF16.indexOfChar([BIII)I", + "java/lang/StringUTF16.indexOfLatin1([BI[BII)I", + "java/lang/StringUTF16.indexOfLatin1([B[B)I", + "java/lang/StringUTF16.putChar([BII)V", + "java/lang/StringUTF16.toBytes([CII)[B"); + } + + if (!getHostArchitectureName().equals("amd64")) { + // Can we implement these on non-AMD64 platforms? C2 seems to. + add(TO_BE_INVESTIGATED, + "sun/misc/Unsafe.getAndAddInt(Ljava/lang/Object;JI)I", + "sun/misc/Unsafe.getAndAddLong(Ljava/lang/Object;JJ)J", + "sun/misc/Unsafe.getAndSetInt(Ljava/lang/Object;JI)I", + "sun/misc/Unsafe.getAndSetLong(Ljava/lang/Object;JJ)J", + "sun/misc/Unsafe.getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;"); + + if (isJDK9OrHigher()) { add(TO_BE_INVESTIGATED, - "java/util/zip/CRC32C.updateBytes(I[BII)I", - "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I"); + "jdk/internal/misc/Unsafe.getAndAddInt(Ljava/lang/Object;JI)I", + "jdk/internal/misc/Unsafe.getAndAddLong(Ljava/lang/Object;JJ)J", + "jdk/internal/misc/Unsafe.getAndSetInt(Ljava/lang/Object;JI)I", + "jdk/internal/misc/Unsafe.getAndSetLong(Ljava/lang/Object;JJ)J", + "jdk/internal/misc/Unsafe.getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C", + "jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I", + "jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J", + "jdk/internal/misc/Unsafe.getShortUnaligned(Ljava/lang/Object;J)S", + "jdk/internal/misc/Unsafe.putCharUnaligned(Ljava/lang/Object;JC)V", + "jdk/internal/misc/Unsafe.putIntUnaligned(Ljava/lang/Object;JI)V", + "jdk/internal/misc/Unsafe.putLongUnaligned(Ljava/lang/Object;JJ)V", + "jdk/internal/misc/Unsafe.putShortUnaligned(Ljava/lang/Object;JS)V"); } } - if (!config.useAESIntrinsics) { - // Registration of the AES plugins is guarded by UseAESIntrinsics - if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { + HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); + GraalHotSpotVMConfig config = rt.getVMConfig(); + + /* + * The intrinsics down here are known to be implemented but they are not always enabled on + * the HotSpot side (e.g., because they require certain CPU features). So, we are ignoring + * them if the HotSpot config tells us that they can't be used. + */ + + // CRC32 intrinsics + if (!config.useCRC32Intrinsics) { + add(IGNORE, "java/util/zip/CRC32.update(II)I"); + if (isJDK9OrHigher()) { add(IGNORE, - "com/sun/crypto/provider/AESCrypt.decryptBlock([BI[BI)V", - "com/sun/crypto/provider/AESCrypt.encryptBlock([BI[BI)V", - "com/sun/crypto/provider/CipherBlockChaining.decrypt([BII[BI)I", - "com/sun/crypto/provider/CipherBlockChaining.encrypt([BII[BI)I"); + "java/util/zip/CRC32.updateByteBuffer0(IJII)I", + "java/util/zip/CRC32.updateBytes0(I[BII)I"); } else { + add(IGNORE, + "java/util/zip/CRC32.updateByteBuffer(IJII)I", + "java/util/zip/CRC32.updateBytes(I[BII)I"); + } + } + + // AES intrinsics + if (!config.useAESIntrinsics) { + if (isJDK9OrHigher()) { add(IGNORE, "com/sun/crypto/provider/AESCrypt.implDecryptBlock([BI[BI)V", "com/sun/crypto/provider/AESCrypt.implEncryptBlock([BI[BI)V", "com/sun/crypto/provider/CipherBlockChaining.implDecrypt([BII[BI)I", "com/sun/crypto/provider/CipherBlockChaining.implEncrypt([BII[BI)I"); - } - } - if (!config.useMultiplyToLenIntrinsic()) { - // Registration of the AES plugins is guarded by UseAESIntrinsics - if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { - add(IGNORE, "java/math/BigInteger.multiplyToLen([II[II[I)[I"); } else { - add(IGNORE, "java/math/BigInteger.implMultiplyToLen([II[II[I)[I"); + add(IGNORE, + "com/sun/crypto/provider/AESCrypt.decryptBlock([BI[BI)V", + "com/sun/crypto/provider/AESCrypt.encryptBlock([BI[BI)V", + "com/sun/crypto/provider/CipherBlockChaining.decrypt([BII[BI)I", + "com/sun/crypto/provider/CipherBlockChaining.encrypt([BII[BI)I"); } } + + // BigInteger intrinsics + if (!config.useMultiplyToLenIntrinsic()) { + if (isJDK9OrHigher()) { + add(IGNORE, "java/math/BigInteger.implMultiplyToLen([II[II[I)[I"); + } else { + add(IGNORE, "java/math/BigInteger.multiplyToLen([II[II[I)[I"); + } + } + if (!config.useMulAddIntrinsic()) { + add(IGNORE, "java/math/BigInteger.implMulAdd([I[IIII)I"); + } + if (!config.useMontgomeryMultiplyIntrinsic()) { + add(IGNORE, "java/math/BigInteger.implMontgomeryMultiply([I[I[IIJ[I)[I"); + } + if (!config.useMontgomerySquareIntrinsic()) { + add(IGNORE, "java/math/BigInteger.implMontgomerySquare([I[IIJ[I)[I"); + } + if (!config.useSquareToLenIntrinsic()) { + add(IGNORE, "java/math/BigInteger.implSquareToLen([II[II)[I"); + } + + // SHA intrinsics + if (!config.useSHA1Intrinsics()) { + if (isJDK9OrHigher()) { + add(IGNORE, "sun/security/provider/SHA.implCompress0([BI)V"); + } else { + add(IGNORE, "sun/security/provider/SHA.implCompress([BI)V"); + } + } + if (!config.useSHA256Intrinsics()) { + if (isJDK9OrHigher()) { + add(IGNORE, "sun/security/provider/SHA2.implCompress0([BI)V"); + } else { + add(IGNORE, "sun/security/provider/SHA2.implCompress([BI)V"); + } + } + if (!config.useSHA512Intrinsics()) { + if (isJDK9OrHigher()) { + add(IGNORE, "sun/security/provider/SHA5.implCompress0([BI)V"); + } else { + add(IGNORE, "sun/security/provider/SHA5.implCompress([BI)V"); + } + } + } + + private static boolean isJDK9OrHigher() { + return JDK9Method.JAVA_SPECIFICATION_VERSION >= 9; } private static String getHostArchitectureName() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java index 4f53585d4d4..dea1d25a430 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java @@ -106,7 +106,12 @@ public class CompilationWrapperTest extends GraalCompilerTest { final int maxProblems = 4; Probe[] probes = { new Probe("To capture more information for diagnosing or reporting a compilation", maxProblems), - new Probe("Retrying compilation of", maxProblems), + new Probe("Retrying compilation of", maxProblems) { + @Override + String test() { + return actualOccurrences > 0 && actualOccurrences <= maxProblems ? null : String.format("expected occurrences to be in [1 .. %d]", maxProblems); + } + }, new Probe("adjusting CompilationFailureAction from Diagnose to Print", 1), new Probe("adjusting CompilationFailureAction from Print to Silent", 1), }; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStackIntrospectionTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStackIntrospectionTest.java new file mode 100644 index 00000000000..98692350b86 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStackIntrospectionTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017, 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.graalvm.compiler.hotspot.test; + +import java.util.function.Function; + +import org.graalvm.compiler.test.GraalTest; +import org.junit.Assume; +import org.junit.Test; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; +import jdk.vm.ci.code.stack.InspectedFrame; +import jdk.vm.ci.code.stack.StackIntrospection; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Create a single object which is referenced from a local, the expression stack and the lock state + * and then ensure that identity is maintained when the frame is forced to be materialized by + * {@link InspectedFrame#materializeVirtualObjects(boolean)}. + */ +public class HotSpotStackIntrospectionTest extends HotSpotGraalCompilerTest { + + static StackIntrospection stackIntrospection = HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getStackIntrospection(); + static volatile int v; + + public static void testSynchronizedSnippet(Function f) { + Object a = new Object(); + synchronized (a) { + testOnStack(a, forceFrameState(a, f), a); + // This object should be locked so try to notify on it + a.notify(); + } + } + + public static void testSnippet(Function f) { + Object a = new Object(); + testOnStack(a, forceFrameState(a, f), a); + } + + private static void testOnStack(Object a, Object a2, Object a3) { + if (a != a2 || a != a3) { + throw new InternalError(); + } + } + + private static Object forceFrameState(Object a, Function f) { + // Use a volatile store to ensure a FrameState is captured after this point. + v++; + f.apply(null); + return a; + } + + @Test(timeout = 20000) + public void run() throws InvalidInstalledCodeException { + // The JDK9 bits are currently broken + Assume.assumeTrue(GraalTest.Java8OrEarlier); + test("testSnippet"); + } + + @Test(timeout = 20000) + public void runSynchronized() throws InvalidInstalledCodeException { + // The JDK9 bits are currently broken + Assume.assumeTrue(GraalTest.Java8OrEarlier); + test("testSynchronizedSnippet"); + } + + private void test(String name) throws InvalidInstalledCodeException { + ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(name)); + Function f = o -> { + stackIntrospection.iterateFrames(null, null, 0, frame -> { + if (frame.getMethod().equals(method)) { + frame.materializeVirtualObjects(true); + } + return null; + }); + return null; + }; + InstalledCode code = getCode(method); + code.executeVarargs(f); + } + +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotUnsafeSubstitutionTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotUnsafeSubstitutionTest.java index 7864f301c10..bbbadb9df58 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotUnsafeSubstitutionTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotUnsafeSubstitutionTest.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.test; +import org.graalvm.compiler.hotspot.meta.HotSpotUnsafeSubstitutions; import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; import org.junit.Test; @@ -56,7 +57,7 @@ public class HotSpotUnsafeSubstitutionTest extends MethodSubstitutionTest { @Test public void testUnsafeSubstitutions() throws Exception { - testGraph("unsafeCopyMemory"); + testGraph("unsafeCopyMemory", HotSpotUnsafeSubstitutions.copyMemoryName); } public void unsafeCopyMemory(Object srcBase, long srcOffset, Object dstBase, long dstOffset, long bytes) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java index 15e709c3056..97c0c281bc4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -165,6 +165,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess { public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class); public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class); public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class); + public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false); private final boolean useMultiplyToLenIntrinsic = getFlag("UseMultiplyToLenIntrinsic", Boolean.class); private final boolean useSHA1Intrinsics = getFlag("UseSHA1Intrinsics", Boolean.class); @@ -594,6 +595,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess { public final int basicLockSize = getFieldValue("CompilerToVM::Data::sizeof_BasicLock", Integer.class, "int"); public final int basicLockDisplacedHeaderOffset = getFieldOffset("BasicLock::_displaced_header", Integer.class, "markOop"); + public final int threadPollingPageOffset = getFieldOffset("Thread::_polling_page", Integer.class, "address", -1); public final int threadAllocatedBytesOffset = getFieldOffset("Thread::_allocated_bytes", Integer.class, "jlong"); public final int tlabRefillWasteIncrement = getFlag("TLABWasteIncrement", Integer.class); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index d3c57cfe2c0..395521ad0fd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -103,6 +103,7 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoweredCallTargetNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StartNode; @@ -254,7 +255,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider instanceofSnippets.lower(instanceOfDynamicNode, tool); } else { ValueNode mirror = instanceOfDynamicNode.getMirrorOrHub(); - if (mirror.stamp().getStackKind() == JavaKind.Object) { + if (mirror.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Object) { ClassGetHubNode classGetHub = graph.unique(new ClassGetHubNode(mirror)); instanceOfDynamicNode.setMirror(classGetHub); } @@ -409,7 +410,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getHub().isConstant(); AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().klassLayoutHelperOffset); - n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), null, BarrierType.NONE))); + n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(NodeView.DEFAULT), null, BarrierType.NONE))); } private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) { @@ -422,11 +423,12 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions()); AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(), - null, BarrierType.NONE)); + FloatingReadNode read = graph.unique( + new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(NodeView.DEFAULT), + null, BarrierType.NONE)); if (vmConfig.classMirrorIsHandle) { AddressNode address = createOffsetAddress(graph, read, 0); - read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(), null, BarrierType.NONE)); + read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(NodeView.DEFAULT), null, BarrierType.NONE)); } n.replaceAtUsagesAndDelete(read); } @@ -439,7 +441,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getValue().isConstant(); AddressNode address = createOffsetAddress(graph, n.getValue(), runtime.getVMConfig().klassOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), null, BarrierType.NONE)); + FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(NodeView.DEFAULT), null, BarrierType.NONE)); n.replaceAtUsagesAndDelete(read); } @@ -448,7 +450,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); NodeInputList parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); - if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { + if (!callTarget.isStatic() && receiver.stamp(NodeView.DEFAULT) instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool); parameters.set(0, nonNullReceiver); receiver = nonNullReceiver; @@ -586,7 +588,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider int size = osrLocal.getStackKind().getSlotCount(); int offset = localsOffset - (osrLocal.index() + size - 1) * wordSize; AddressNode address = createOffsetAddress(graph, buffer, offset); - ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(), BarrierType.NONE)); + ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(NodeView.DEFAULT), BarrierType.NONE)); osrLocal.replaceAndDelete(load); graph.addBeforeFixed(migrationEnd, load); } @@ -609,7 +611,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider // load the displaced mark from the osr buffer AddressNode addressDisplacedHeader = createOffsetAddress(graph, buffer, offsetDisplacedHeader); - ReadNode loadDisplacedHeader = graph.add(new ReadNode(addressDisplacedHeader, any(), lock.stamp(), BarrierType.NONE)); + ReadNode loadDisplacedHeader = graph.add(new ReadNode(addressDisplacedHeader, any(), lock.stamp(NodeView.DEFAULT), BarrierType.NONE)); graph.addBeforeFixed(migrationEnd, loadDisplacedHeader); // we need to initialize the stack slot for the lock @@ -623,7 +625,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider // load the lock object from the osr buffer AddressNode addressLockObject = createOffsetAddress(graph, buffer, offsetLockObject); - ReadNode loadObject = graph.add(new ReadNode(addressLockObject, any(), lock.stamp(), BarrierType.NONE)); + ReadNode loadObject = graph.add(new ReadNode(addressLockObject, any(), lock.stamp(NodeView.DEFAULT), BarrierType.NONE)); lock.replaceAndDelete(loadObject); graph.addBeforeFixed(migrationEnd, loadObject); } @@ -688,7 +690,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } StructuredGraph graph = node.graph(); - ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(), node.getArguments())); + ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(NodeView.DEFAULT), node.getArguments())); graph.replaceFixedWithFixed(node, foreignCallNode); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 5e1504ab14c..84dcaad7b8f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -66,6 +66,7 @@ import org.graalvm.compiler.nodes.DynamicPiNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; @@ -318,7 +319,7 @@ public class HotSpotGraphBuilderPlugins { private static boolean readMetaspaceConstantPoolElement(GraphBuilderContext b, ValueNode constantPoolOop, ValueNode index, JavaKind elementKind, WordTypes wordTypes, GraalHotSpotVMConfig config) { ValueNode constants = getMetaspaceConstantPool(b, constantPoolOop, wordTypes, config); int shift = CodeUtil.log2(wordTypes.getWordKind().getByteCount()); - ValueNode scaledIndex = b.add(new LeftShiftNode(IntegerConvertNode.convert(index, StampFactory.forKind(JavaKind.Long)), b.add(ConstantNode.forInt(shift)))); + ValueNode scaledIndex = b.add(new LeftShiftNode(IntegerConvertNode.convert(index, StampFactory.forKind(JavaKind.Long), NodeView.DEFAULT), b.add(ConstantNode.forInt(shift)))); ValueNode offset = b.add(new AddNode(scaledIndex, b.add(ConstantNode.forLong(config.constantPoolSize)))); AddressNode elementAddress = b.add(new OffsetAddressNode(constants, offset)); boolean notCompressible = false; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java index ec2c62b3eb4..e9f01f60583 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -136,7 +137,7 @@ public class HotSpotInvokeDynamicPlugin implements InvokeDynamicPlugin { ConstantNode appendixNode = ConstantNode.forConstant(appendix, builder.getMetaAccess(), builder.getGraph()); - Stamp appendixStamp = appendixNode.stamp(); + Stamp appendixStamp = appendixNode.stamp(NodeView.DEFAULT); Stamp resolveStamp = treatAppendixAsConstant ? appendixStamp : appendixStamp.unrestricted(); ResolveDynamicConstantNode resolveNode = new ResolveDynamicConstantNode(resolveStamp, appendixNode); ResolveDynamicConstantNode added = builder.append(resolveNode); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index f1c7359eba3..376325e759b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -87,7 +87,7 @@ public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvid // Need to test all fields since there no guarantee under the JMM // about the order in which these fields are written. GraalHotSpotVMConfig config = runtime.getVMConfig(); - if (configType == null || wordTypesType == null || configType == null) { + if (configType == null || wordTypesType == null || runtimeType == null) { wordTypesType = wordTypes.getClass(); runtimeType = runtime.getClass(); configType = config.getClass(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java index 354b8e1f8af..246491cef7d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.hotspot.word.HotSpotOperation; import org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode; import org.graalvm.compiler.hotspot.word.PointerCastNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.calc.IsNullNode; @@ -102,23 +103,23 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { HotspotOpcode opcode = operation.opcode(); ValueNode left = args[0]; ValueNode right = args[1]; - assert left.stamp() instanceof MetaspacePointerStamp : left + " " + left.stamp(); - assert right.stamp() instanceof MetaspacePointerStamp : right + " " + right.stamp(); + assert left.stamp(NodeView.DEFAULT) instanceof MetaspacePointerStamp : left + " " + left.stamp(NodeView.DEFAULT); + assert right.stamp(NodeView.DEFAULT) instanceof MetaspacePointerStamp : right + " " + right.stamp(NodeView.DEFAULT); assert opcode == POINTER_EQ || opcode == POINTER_NE; PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); - b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue)); + b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue, NodeView.DEFAULT)); break; case IS_NULL: assert args.length == 1; ValueNode pointer = args[0]; - assert pointer.stamp() instanceof MetaspacePointerStamp; + assert pointer.stamp(NodeView.DEFAULT) instanceof MetaspacePointerStamp; LogicNode isNull = b.addWithInputs(IsNullNode.create(pointer)); - b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); + b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)), NodeView.DEFAULT)); break; case FROM_POINTER: diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java index ecd8ba0b811..b164b1226b5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CompressionNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; @@ -45,7 +46,7 @@ public final class HotSpotCompressionNode extends CompressionNode { public static final NodeClass TYPE = NodeClass.create(HotSpotCompressionNode.class); public HotSpotCompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) { - super(TYPE, op, input, HotSpotNarrowOopStamp.mkStamp(op, input.stamp(), encoding), encoding); + super(TYPE, op, input, HotSpotNarrowOopStamp.mkStamp(op, input.stamp(NodeView.DEFAULT), encoding), encoding); } public static HotSpotCompressionNode compress(ValueNode input, CompressEncoding encoding) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java index aff5ce9b872..63674b901da 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -42,7 +43,7 @@ public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implement @Input ValueNode value; public InitializeKlassNode(ValueNode value) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java index 2630a60dcd3..b7af9ab772a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; @@ -61,7 +62,7 @@ public class InitializeKlassStubCall extends AbstractMemoryCheckpoint implements protected Constant constant; protected InitializeKlassStubCall(ValueNode value, ValueNode string) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.string = string; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java index 2603e78cee4..85fac77d08b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.hotspot.word.MethodPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -56,14 +57,14 @@ public class LoadConstantIndirectlyFixedNode extends FixedWithNextNode implement protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyFixedNode(ValueNode value) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyFixedNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.constant = null; this.action = action; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java index 8758c02cba3..7cba4506833 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -55,14 +56,14 @@ public class LoadConstantIndirectlyNode extends FloatingNode implements Canonica protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyNode(ValueNode value) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.constant = null; this.action = action; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java index 73202626047..c6b131658aa 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -41,13 +42,13 @@ public class ResolveConstantNode extends DeoptimizingFixedWithNextNode implement protected HotSpotConstantLoadAction action; public ResolveConstantNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.action = action; } public ResolveConstantNode(ValueNode value) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.action = HotSpotConstantLoadAction.RESOLVE; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java index 6a6393b1990..912d295f2d4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.hotspot.nodes.DeoptimizingStubCall; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -59,14 +60,14 @@ public class ResolveConstantStubCall extends DeoptimizingStubCall implements Can protected HotSpotConstantLoadAction action; public ResolveConstantStubCall(ValueNode value, ValueNode string) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.string = string; this.action = HotSpotConstantLoadAction.RESOLVE; } public ResolveConstantStubCall(ValueNode value, ValueNode string, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.string = string; this.action = action; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java index dd3a558d79e..f811e3d923f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -59,7 +60,7 @@ public class ResolveDynamicStubCall extends AbstractMemoryCheckpoint implements protected Constant constant; public ResolveDynamicStubCall(ValueNode value) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java index 116ef56436b..e790daea4fd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java @@ -50,6 +50,7 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StartNode; @@ -185,8 +186,8 @@ public class OnStackReplacementPhase extends Phase { * (if a branch was not parsed for example). In cases when this is possible, we * insert a guard and narrow the OSRLocal stamp at its usages. */ - Stamp narrowedStamp = proxy.value().stamp(); - Stamp unrestrictedStamp = proxy.stamp().unrestricted(); + Stamp narrowedStamp = proxy.value().stamp(NodeView.DEFAULT); + Stamp unrestrictedStamp = proxy.stamp(NodeView.DEFAULT).unrestricted(); ValueNode osrLocal; if (i >= localsSize) { osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, unrestrictedStamp)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java index 07576103017..b3781b00f0e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.hotspot.nodes.profiling.RandomSeedNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -130,7 +131,7 @@ public class FinalizeProfileNodesPhase extends BasePhase { LoopBeginNode loopBegin = (LoopBeginNode) loop.getHeader().getBeginNode(); random = loopRandomValueCache.get(loopBegin); if (random == null) { - PhiNode phi = graph.addWithoutUnique(new ValuePhiNode(seed.stamp(), loopBegin)); + PhiNode phi = graph.addWithoutUnique(new ValuePhiNode(seed.stamp(NodeView.DEFAULT), loopBegin)); phi.addInput(seed); // X_{n+1} = a*X_n + c, using glibc-like constants ValueNode a = ConstantNode.forInt(1103515245, graph); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java index a385134ccb4..62bf05e689e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConvertNode; @@ -118,7 +119,7 @@ public final class ClassGetHubNode extends FloatingNode implements Lowerable, Ca @Override public Node canonical(CanonicalizerTool tool) { - return canonical(this, tool.getMetaAccess(), tool.getConstantReflection(), tool.allUsagesAvailable(), stamp(), clazz); + return canonical(this, tool.getMetaAccess(), tool.getConstantReflection(), tool.allUsagesAvailable(), stamp(NodeView.DEFAULT), clazz); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 29a508882d8..0966cf6f1de 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -45,6 +45,7 @@ import org.graalvm.compiler.nodes.CanonicalizableLocation; import org.graalvm.compiler.nodes.CompressionNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; @@ -124,7 +125,7 @@ public class HotSpotReplacementsUtil { AddressNode address = access.getAddress(); if (address instanceof OffsetAddressNode) { OffsetAddressNode offset = (OffsetAddressNode) address; - assert offset.getBase().stamp().isCompatible(read.stamp()); + assert offset.getBase().stamp(NodeView.DEFAULT).isCompatible(read.stamp(NodeView.DEFAULT)); return offset.getBase(); } } @@ -370,8 +371,8 @@ public class HotSpotReplacementsUtil { public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { ValueNode javaObject = findReadHub(object); if (javaObject != null) { - if (javaObject.stamp() instanceof ObjectStamp) { - ObjectStamp stamp = (ObjectStamp) javaObject.stamp(); + if (javaObject.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { + ObjectStamp stamp = (ObjectStamp) javaObject.stamp(NodeView.DEFAULT); HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess()); if (type.isArray() && !type.getComponentType().isPrimitive()) { int layout = type.layoutHelper(); @@ -437,7 +438,7 @@ public class HotSpotReplacementsUtil { public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { TypeReference constantType = StampTool.typeReferenceOrNull(object); if (constantType != null && constantType.isExact()) { - return ConstantNode.forConstant(read.stamp(), tool.getConstantReflection().asObjectHub(constantType.getType()), tool.getMetaAccess()); + return ConstantNode.forConstant(read.stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(constantType.getType()), tool.getMetaAccess()); } return read; } @@ -448,7 +449,8 @@ public class HotSpotReplacementsUtil { public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { TypeReference constantType = StampTool.typeReferenceOrNull(object); if (constantType != null && constantType.isExact()) { - return ConstantNode.forConstant(read.stamp(), ((HotSpotMetaspaceConstant) tool.getConstantReflection().asObjectHub(constantType.getType())).compress(), tool.getMetaAccess()); + return ConstantNode.forConstant(read.stamp(NodeView.DEFAULT), ((HotSpotMetaspaceConstant) tool.getConstantReflection().asObjectHub(constantType.getType())).compress(), + tool.getMetaAccess()); } return read; } @@ -962,7 +964,7 @@ public class HotSpotReplacementsUtil { AssumptionResult leafType = element.findLeafConcreteSubtype(); if (leafType != null && leafType.canRecordTo(assumptions)) { leafType.recordTo(assumptions); - return ConstantNode.forConstant(read.stamp(), tool.getConstantReflection().asObjectHub(leafType.getResult()), tool.getMetaAccess()); + return ConstantNode.forConstant(read.stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(leafType.getResult()), tool.getMetaAccess()); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java index a28f4559f67..66971954ac3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -65,7 +66,7 @@ public class IdentityHashCodeNode extends FixedWithNextNode implements Canonical @Override public Node canonical(CanonicalizerTool tool) { if (object.isConstant()) { - assert object.stamp() instanceof AbstractObjectStamp; + assert object.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; JavaConstant c = (JavaConstant) object.asConstant(); if (ImmutableCode.getValue(tool.getOptions())) { return this; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java index 29453e464ce..1ca01ebb9b0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java @@ -53,6 +53,7 @@ import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Hints; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -332,7 +333,7 @@ public class InstanceOfSnippets implements Snippets { } else if (replacer.instanceOf instanceof ClassIsAssignableFromNode) { ClassIsAssignableFromNode isAssignable = (ClassIsAssignableFromNode) replacer.instanceOf; Arguments args = new Arguments(isAssignableFrom, isAssignable.graph().getGuardsStage(), tool.getLoweringStage()); - assert ((ObjectStamp) isAssignable.getThisClass().stamp()).nonNull(); + assert ((ObjectStamp) isAssignable.getThisClass().stamp(NodeView.DEFAULT)).nonNull(); args.add("thisClassNonNull", isAssignable.getThisClass()); args.add("otherClass", isAssignable.getOtherClass()); args.add("trueValue", replacer.trueValue); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java index 7cbcd3887f9..bdde73fd117 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; @@ -83,7 +84,7 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic public boolean inferStamp() { if (klass instanceof LoadHubNode) { LoadHubNode hub = (LoadHubNode) klass; - Stamp hubStamp = hub.getValue().stamp(); + Stamp hubStamp = hub.getValue().stamp(NodeView.DEFAULT); if (hubStamp instanceof ObjectStamp) { ObjectStamp objectStamp = (ObjectStamp) hubStamp; ResolvedJavaType type = objectStamp.type(); @@ -108,7 +109,7 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic if (tool.allUsagesAvailable() && hasNoUsages()) { return null; } else { - return canonical(this, config, klass, stamp(), tool.getConstantReflection(), tool.getMetaAccess()); + return canonical(this, config, klass, stamp(NodeView.DEFAULT), tool.getConstantReflection(), tool.getMetaAccess()); } } @@ -123,7 +124,7 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic } if (klass instanceof LoadHubNode) { LoadHubNode hub = (LoadHubNode) klass; - Stamp hubStamp = hub.getValue().stamp(); + Stamp hubStamp = hub.getValue().stamp(NodeView.DEFAULT); if (hubStamp instanceof ObjectStamp) { ObjectStamp ostamp = (ObjectStamp) hubStamp; HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java index 83a6060d95d..40fe62ea766 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java @@ -99,6 +99,7 @@ import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -736,7 +737,7 @@ public class MonitorSnippets implements Snippets { StructuredGraph graph = monitorenterNode.graph(); checkBalancedMonitors(graph, tool); - assert ((ObjectStamp) monitorenterNode.object().stamp()).nonNull(); + assert ((ObjectStamp) monitorenterNode.object().stamp(NodeView.DEFAULT)).nonNull(); Arguments args; if (useFastLocking) { @@ -781,7 +782,7 @@ public class MonitorSnippets implements Snippets { } public static boolean isTracingEnabledForType(ValueNode object) { - ResolvedJavaType type = StampTool.typeOrNull(object.stamp()); + ResolvedJavaType type = StampTool.typeOrNull(object.stamp(NodeView.DEFAULT)); String filter = TraceMonitorsTypeFilter.getValue(object.getOptions()); if (filter == null) { return false; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java index b12cf66155f..02bf3438173 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -62,14 +63,14 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu @Override protected Stamp computeStamp(ValueNode object) { - if (getConcreteType(object.stamp()) != null) { - return AbstractPointerStamp.pointerNonNull(object.stamp()); + if (getConcreteType(object.stamp(NodeView.DEFAULT)) != null) { + return AbstractPointerStamp.pointerNonNull(object.stamp(NodeView.DEFAULT)); } /* * If this call can't be intrinsified don't report a non-null stamp, otherwise the stamp * would change when this is lowered back to an invoke and we might lose a null check. */ - return AbstractPointerStamp.pointerMaybeNull(object.stamp()); + return AbstractPointerStamp.pointerMaybeNull(object.stamp(NodeView.DEFAULT)); } @Override @@ -91,16 +92,16 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu } assert snippetGraph != null : "ObjectCloneSnippets should be installed"; - assert getConcreteType(stamp()) != null; + assert getConcreteType(stamp(NodeView.DEFAULT)) != null; return lowerReplacement((StructuredGraph) snippetGraph.copy(getDebug()), tool); } assert false : "unhandled array type " + type.getComponentType().getJavaKind(); } else { Assumptions assumptions = graph().getAssumptions(); - type = getConcreteType(getObject().stamp()); + type = getConcreteType(getObject().stamp(NodeView.DEFAULT)); if (type != null) { StructuredGraph newGraph = new StructuredGraph.Builder(graph().getOptions(), graph().getDebug(), AllowAssumptions.ifNonNull(assumptions)).build(); - ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp()))); + ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp(NodeView.DEFAULT)))); NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); newGraph.addAfterFixed(newGraph.start(), newInstance); ReturnNode returnNode = newGraph.add(new ReturnNode(newInstance)); @@ -111,12 +112,12 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu newGraph.addBeforeFixed(returnNode, load); newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load))); } - assert getConcreteType(stamp()) != null; + assert getConcreteType(stamp(NodeView.DEFAULT)) != null; return lowerReplacement(newGraph, tool); } } } - assert getConcreteType(stamp()) == null; + assert getConcreteType(stamp(NodeView.DEFAULT)) == null; return null; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java index b4cdc08ace8..9a3c4011948 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java @@ -66,6 +66,7 @@ import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode; @@ -447,7 +448,7 @@ public class WriteBarrierSnippets implements Snippets { } ValueNode expected = writeBarrierPre.getExpectedObject(); - if (expected != null && expected.stamp() instanceof NarrowOopStamp) { + if (expected != null && expected.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) { assert oopEncoding != null; expected = HotSpotCompressionNode.uncompress(expected, oopEncoding); } @@ -472,7 +473,7 @@ public class WriteBarrierSnippets implements Snippets { } ValueNode expected = readBarrier.getExpectedObject(); - if (expected != null && expected.stamp() instanceof NarrowOopStamp) { + if (expected != null && expected.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) { assert oopEncoding != null; expected = HotSpotCompressionNode.uncompress(expected, oopEncoding); } @@ -503,7 +504,7 @@ public class WriteBarrierSnippets implements Snippets { } ValueNode value = writeBarrierPost.getValue(); - if (value.stamp() instanceof NarrowOopStamp) { + if (value.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) { assert oopEncoding != null; value = HotSpotCompressionNode.uncompress(value, oopEncoding); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java index 8f4e370020f..863db348004 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java @@ -44,6 +44,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; @@ -143,7 +144,7 @@ public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements FixedWithNextNode basePtr = graph().add(new GetObjectAddressNode(base)); graph().addBeforeFixed(this, basePtr); Stamp wordStamp = StampFactory.forKind(runtime.getTarget().wordJavaKind); - ValueNode wordPos = IntegerConvertNode.convert(pos, wordStamp, graph()); + ValueNode wordPos = IntegerConvertNode.convert(pos, wordStamp, graph(), NodeView.DEFAULT); int shift = CodeUtil.log2(getArrayIndexScale(elementKind)); ValueNode scaledIndex = graph().unique(new LeftShiftNode(wordPos, ConstantNode.forInt(shift, graph()))); ValueNode offset = graph().unique(new AddNode(scaledIndex, ConstantNode.forIntegerStamp(wordStamp, getArrayBaseOffset(elementKind), graph()))); @@ -160,8 +161,8 @@ public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements ValueNode srcAddr = computeBase(getSource(), getSourcePosition()); ValueNode destAddr = computeBase(getDestination(), getDestinationPosition()); ValueNode len = getLength(); - if (len.stamp().getStackKind() != JavaKind.Long) { - len = IntegerConvertNode.convert(len, StampFactory.forKind(JavaKind.Long), graph()); + if (len.stamp(NodeView.DEFAULT).getStackKind() != JavaKind.Long) { + len = IntegerConvertNode.convert(len, StampFactory.forKind(JavaKind.Long), graph(), NodeView.DEFAULT); } ForeignCallNode call = graph.add(new ForeignCallNode(runtime.getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len)); call.setStateAfter(stateAfter()); @@ -232,8 +233,8 @@ public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements // Can treat as disjoint disjoint = true; } - PrimitiveConstant constantSrc = (PrimitiveConstant) srcPos.stamp().asConstant(); - PrimitiveConstant constantDst = (PrimitiveConstant) destPos.stamp().asConstant(); + PrimitiveConstant constantSrc = (PrimitiveConstant) srcPos.stamp(NodeView.DEFAULT).asConstant(); + PrimitiveConstant constantDst = (PrimitiveConstant) destPos.stamp(NodeView.DEFAULT).asConstant(); if (constantSrc != null && constantDst != null) { if (!aligned) { aligned = isHeapWordAligned(constantSrc, componentKind) && isHeapWordAligned(constantDst, componentKind); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java index a8c59ade39b..216fb279e0f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java @@ -54,6 +54,7 @@ import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -90,11 +91,12 @@ public class ArrayCopySnippets implements Snippets { private enum ArrayCopyTypeCheck { UNDEFINED_ARRAY_TYPE_CHECK, - // we know that both objects are arrays and have the same type + // either we know that both objects are arrays and have the same type, + // or we apply generic array copy snippet, which enforces type check NO_ARRAY_TYPE_CHECK, // can be used when we know that one of the objects is a primitive array HUB_BASED_ARRAY_TYPE_CHECK, - // must be used when we don't have sufficient information to use one of the others + // can be used when we know that one of the objects is an object array LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK } @@ -232,18 +234,18 @@ public class ArrayCopySnippets implements Snippets { @Snippet(allowPartialIntrinsicArgumentMismatch = true) public static void genericArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { - if (probability(FREQUENT_PROBABILITY, length > 0)) { - counters.genericArraycopyDifferentTypeCounter.inc(); - counters.genericArraycopyDifferentTypeCopiedCounter.add(length); - int copiedElements = GenericArrayCopyCallNode.genericArraycopy(src, srcPos, dest, destPos, length); - if (probability(SLOW_PATH_PROBABILITY, copiedElements != 0)) { - /* - * the stub doesn't throw the ArrayStoreException, but returns the number of copied - * elements (xor'd with -1). - */ - copiedElements ^= -1; - System.arraycopy(src, srcPos + copiedElements, dest, destPos + copiedElements, length - copiedElements); - } + // The length > 0 check should not be placed here because generic array copy stub should + // enforce type check. This is fine performance-wise because this snippet is rarely used. + counters.genericArraycopyDifferentTypeCounter.inc(); + counters.genericArraycopyDifferentTypeCopiedCounter.add(length); + int copiedElements = GenericArrayCopyCallNode.genericArraycopy(src, srcPos, dest, destPos, length); + if (probability(SLOW_PATH_PROBABILITY, copiedElements != 0)) { + /* + * the stub doesn't throw the ArrayStoreException, but returns the number of copied + * elements (xor'd with -1). + */ + copiedElements ^= -1; + System.arraycopy(src, srcPos + copiedElements, dest, destPos + copiedElements, length - copiedElements); } } @@ -275,21 +277,14 @@ public class ArrayCopySnippets implements Snippets { } else if (arrayTypeCheck == ArrayCopyTypeCheck.LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK) { KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); - checkArrayType(srcHub); - checkArrayType(destHub); + if (probability(SLOW_PATH_PROBABILITY, readLayoutHelper(srcHub) != readLayoutHelper(destHub))) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } } else { ReplacementsUtil.staticAssert(false, "unknown array type check"); } } - private static int checkArrayType(KlassPointer nonNullHub) { - int layoutHelper = readLayoutHelper(nonNullHub); - if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) { - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); - } - return layoutHelper; - } - static class Counters { final SnippetCounter checkSuccessCounter; final SnippetCounter checkAIOOBECounter; @@ -381,8 +376,8 @@ public class ArrayCopySnippets implements Snippets { SnippetInfo snippetInfo; ArrayCopyTypeCheck arrayTypeCheck; - ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp()); - ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp()); + ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp(NodeView.DEFAULT)); + ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp(NodeView.DEFAULT)); if (!canBeArray(srcType) || !canBeArray(destType)) { // at least one of the objects is definitely not an array - use the native call // right away as the copying will fail anyways @@ -399,7 +394,8 @@ public class ArrayCopySnippets implements Snippets { } else if (srcComponentType == null && destComponentType == null) { // we don't know anything about the types - use the generic copying snippetInfo = arraycopyGenericSnippet; - arrayTypeCheck = ArrayCopyTypeCheck.LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK; + // no need for additional type check to avoid duplicated work + arrayTypeCheck = ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK; } else if (srcComponentType != null && destComponentType != null) { if (!srcComponentType.isPrimitive() && !destComponentType.isPrimitive()) { // it depends on the array content if the copy succeeds - we need @@ -416,14 +412,14 @@ public class ArrayCopySnippets implements Snippets { } else { ResolvedJavaType nonNullComponentType = srcComponentType != null ? srcComponentType : destComponentType; if (nonNullComponentType.isPrimitive()) { - // one involved object is a primitive array - we can safely assume that we - // are copying primitive arrays + // one involved object is a primitive array - it is sufficient to directly + // compare the hub. snippetInfo = arraycopyExactSnippet; arrayTypeCheck = ArrayCopyTypeCheck.HUB_BASED_ARRAY_TYPE_CHECK; elementKind = nonNullComponentType.getJavaKind(); } else { - // one involved object is an object array - we can safely assume that we are - // copying object arrays that might require a store check + // one involved object is an object array - the other array's element type + // may be primitive or object, hence we compare the layout helper. snippetInfo = arraycopyCheckcastSnippet; arrayTypeCheck = ArrayCopyTypeCheck.LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK; } @@ -432,7 +428,12 @@ public class ArrayCopySnippets implements Snippets { // a few special cases that are easier to handle when all other variables already have a // value - if (arraycopy.getLength().isConstant() && arraycopy.getLength().asJavaConstant().asLong() == 0) { + if (snippetInfo != arraycopyNativeSnippet && snippetInfo != arraycopyGenericSnippet && arraycopy.getLength().isConstant() && arraycopy.getLength().asJavaConstant().asLong() == 0) { + // Copying 0 element between object arrays with conflicting types will not throw an + // exception - once we pass the preliminary element type checks that we are not + // mixing arrays of different basic types, ArrayStoreException is only thrown when + // an *astore would have thrown it. Therefore, copying null between object arrays + // with conflicting types will also succeed (we do not optimize for such case here). snippetInfo = arraycopyZeroLengthSnippet; } else if (snippetInfo == arraycopyExactSnippet && shouldUnroll(arraycopy.getLength())) { snippetInfo = arraycopyUnrolledSnippet; @@ -495,8 +496,8 @@ public class ArrayCopySnippets implements Snippets { } public static JavaKind selectComponentKind(BasicArrayCopyNode arraycopy) { - ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp()); - ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp()); + ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp(NodeView.DEFAULT)); + ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp(NodeView.DEFAULT)); if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { return null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java index e90d486a98d..e6fb867a83e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; @@ -115,9 +116,10 @@ public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint i graph().addBeforeFixed(this, basePtr); int shift = CodeUtil.log2(getArrayIndexScale(JavaKind.Object)); - ValueNode extendedPos = IntegerConvertNode.convert(pos, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph()); + ValueNode extendedPos = IntegerConvertNode.convert(pos, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph(), NodeView.DEFAULT); ValueNode scaledIndex = graph().unique(new LeftShiftNode(extendedPos, ConstantNode.forInt(shift, graph()))); - ValueNode offset = graph().unique(new AddNode(scaledIndex, ConstantNode.forIntegerBits(PrimitiveStamp.getBits(scaledIndex.stamp()), getArrayBaseOffset(JavaKind.Object), graph()))); + ValueNode offset = graph().unique( + new AddNode(scaledIndex, ConstantNode.forIntegerBits(PrimitiveStamp.getBits(scaledIndex.stamp(NodeView.DEFAULT)), getArrayBaseOffset(JavaKind.Object), graph()))); return graph().unique(new OffsetAddressNode(basePtr, offset)); } @@ -129,8 +131,8 @@ public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint i ValueNode srcAddr = computeBase(getSource(), getSourcePosition()); ValueNode destAddr = computeBase(getDestination(), getDestinationPosition()); ValueNode len = getLength(); - if (len.stamp().getStackKind() != runtime.getTarget().wordJavaKind) { - len = IntegerConvertNode.convert(len, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph()); + if (len.stamp(NodeView.DEFAULT).getStackKind() != runtime.getTarget().wordJavaKind) { + len = IntegerConvertNode.convert(len, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph(), NodeView.DEFAULT); } ForeignCallNode call = graph.add(new ForeignCallNode(runtime.getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len, superCheckOffset, destElemKlass)); call.setStateAfter(stateAfter()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java index 1017b07c2b2..70373bfe4e1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IntegerConvertNode; @@ -106,8 +107,8 @@ public final class GenericArrayCopyCallNode extends AbstractMemoryCheckpoint imp } private ValueNode wordValue(ValueNode value) { - if (value.stamp().getStackKind() != runtime.getTarget().wordJavaKind) { - return IntegerConvertNode.convert(value, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph()); + if (value.stamp(NodeView.DEFAULT).getStackKind() != runtime.getTarget().wordJavaKind) { + return IntegerConvertNode.convert(value, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph(), NodeView.DEFAULT); } return value; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java index 658c3ce30fb..01dc9cdab21 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; @@ -120,7 +121,7 @@ public abstract class SnippetStub extends Stub implements Snippets { for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { int index = param.index(); if (method.getParameterAnnotation(NonNullParameter.class, index) != null) { - param.setStamp(param.stamp().join(StampFactory.objectNonNull())); + param.setStamp(param.stamp(NodeView.DEFAULT).join(StampFactory.objectNonNull())); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/PointerCastNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/PointerCastNode.java index 866ba59bd0b..18a27d002e5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/PointerCastNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/PointerCastNode.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -59,7 +60,7 @@ public final class PointerCastNode extends FloatingNode implements LIRLowerable, @Override public void generate(NodeLIRBuilderTool generator) { Value value = generator.operand(input); - assert value.getValueKind().equals(generator.getLIRGeneratorTool().getLIRKind(stamp())) : "PointerCastNode shouldn't change the LIRKind"; + assert value.getValueKind().equals(generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT))) : "PointerCastNode shouldn't change the LIRKind"; generator.setResult(this, value); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 8a8299098fe..e39464a0f6a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -330,6 +330,7 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ReturnNode; @@ -1092,71 +1093,71 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genIntegerAdd(ValueNode x, ValueNode y) { - return AddNode.create(x, y); + return AddNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genIntegerSub(ValueNode x, ValueNode y) { - return SubNode.create(x, y); + return SubNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genIntegerMul(ValueNode x, ValueNode y) { - return MulNode.create(x, y); + return MulNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genFloatAdd(ValueNode x, ValueNode y) { - return AddNode.create(x, y); + return AddNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genFloatSub(ValueNode x, ValueNode y) { - return SubNode.create(x, y); + return SubNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genFloatMul(ValueNode x, ValueNode y) { - return MulNode.create(x, y); + return MulNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genFloatDiv(ValueNode x, ValueNode y) { - return FloatDivNode.create(x, y); + return FloatDivNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genFloatRem(ValueNode x, ValueNode y) { - return new RemNode(x, y); + return RemNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genIntegerDiv(ValueNode x, ValueNode y) { - return new SignedDivNode(x, y); + return SignedDivNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genIntegerRem(ValueNode x, ValueNode y) { - return new SignedRemNode(x, y); + return SignedRemNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genNegateOp(ValueNode x) { - return NegateNode.create(x); + return NegateNode.create(x, NodeView.DEFAULT); } protected ValueNode genLeftShift(ValueNode x, ValueNode y) { - return LeftShiftNode.create(x, y); + return LeftShiftNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genRightShift(ValueNode x, ValueNode y) { - return RightShiftNode.create(x, y); + return RightShiftNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) { - return new UnsignedRightShiftNode(x, y); + return UnsignedRightShiftNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genAnd(ValueNode x, ValueNode y) { - return AndNode.create(x, y); + return AndNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genOr(ValueNode x, ValueNode y) { - return OrNode.create(x, y); + return OrNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genXor(ValueNode x, ValueNode y) { - return XorNode.create(x, y); + return XorNode.create(x, y, NodeView.DEFAULT); } protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) { @@ -1164,19 +1165,19 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) { - return FloatConvertNode.create(op, input); + return FloatConvertNode.create(op, input, NodeView.DEFAULT); } protected ValueNode genNarrow(ValueNode input, int bitCount) { - return NarrowNode.create(input, bitCount); + return NarrowNode.create(input, bitCount, NodeView.DEFAULT); } protected ValueNode genSignExtend(ValueNode input, int bitCount) { - return SignExtendNode.create(input, bitCount); + return SignExtendNode.create(input, bitCount, NodeView.DEFAULT); } protected ValueNode genZeroExtend(ValueNode input, int bitCount) { - return ZeroExtendNode.create(input, bitCount); + return ZeroExtendNode.create(input, bitCount, NodeView.DEFAULT); } protected void genGoto() { @@ -1191,15 +1192,15 @@ public class BytecodeParser implements GraphBuilderContext { } protected LogicNode genObjectEquals(ValueNode x, ValueNode y) { - return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y); + return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, NodeView.DEFAULT); } protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) { - return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y); + return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT); } protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) { - return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y); + return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT); } protected ValueNode genUnique(ValueNode x) { @@ -1219,7 +1220,7 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode exception = frameState.pop(JavaKind.Object); FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); - ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck)); + ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp(NodeView.DEFAULT).join(objectNonNull()), nullCheck)); lastInstr.setNext(handleException(nonNullException, bci(), false)); } @@ -1244,7 +1245,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genConditional(ValueNode x) { - return ConditionalNode.create((LogicNode) x); + return ConditionalNode.create((LogicNode) x, NodeView.DEFAULT); } protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { @@ -1275,7 +1276,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode emitExplicitNullCheck(ValueNode receiver) { - if (StampTool.isPointerNonNull(receiver.stamp())) { + if (StampTool.isPointerNonNull(receiver.stamp(NodeView.DEFAULT))) { return receiver; } BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class)); @@ -1293,7 +1294,7 @@ public class BytecodeParser implements GraphBuilderContext { protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) { AbstractBeginNode trueSucc = graph.add(new BeginNode()); BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); - append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY)); + append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length, NodeView.DEFAULT)), trueSucc, exception, FAST_PATH_PROBABILITY)); lastInstr = trueSucc; exception.setStateAfter(createFrameState(bci(), exception)); @@ -1803,7 +1804,7 @@ public class BytecodeParser implements GraphBuilderContext { this.args = args; this.resultType = resultType; this.beforeStackSize = frameState.stackSize(); - this.needsNullCheck = !targetMethod.isStatic() && args[0].getStackKind() == JavaKind.Object && !StampTool.isPointerNonNull(args[0].stamp()); + this.needsNullCheck = !targetMethod.isStatic() && args[0].getStackKind() == JavaKind.Object && !StampTool.isPointerNonNull(args[0].stamp(NodeView.DEFAULT)); this.nodeCount = graph.getNodeCount(); this.mark = graph.getMark(); } @@ -1817,7 +1818,8 @@ public class BytecodeParser implements GraphBuilderContext { int expectedStackSize = beforeStackSize + resultType.getSlotCount(); assert expectedStackSize == frameState.stackSize() : error("plugin manipulated the stack incorrectly: expected=%d, actual=%d", expectedStackSize, frameState.stackSize()); NodeIterable newNodes = graph.getNewNodes(mark); - assert !needsNullCheck || isPointerNonNull(args[0].stamp()) : error("plugin needs to null check the receiver of %s: receiver=%s", targetMethod.format("%H.%n(%p)"), args[0]); + assert !needsNullCheck || isPointerNonNull(args[0].stamp(NodeView.DEFAULT)) : error("plugin needs to null check the receiver of %s: receiver=%s", targetMethod.format("%H.%n(%p)"), + args[0]); for (Node n : newNodes) { if (n instanceof StateSplit) { StateSplit stateSplit = (StateSplit) n; @@ -1891,7 +1893,7 @@ public class BytecodeParser implements GraphBuilderContext { LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver)); LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub)); ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess())); - LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected)); + LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected, NodeView.DEFAULT)); JavaTypeProfile profile = null; if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { @@ -2394,7 +2396,7 @@ public class BytecodeParser implements GraphBuilderContext { if (kind != returnKind) { // sub-word integer assert returnKind.isNumericInteger() && returnKind.getStackKind() == JavaKind.Int; - IntegerStamp stamp = (IntegerStamp) value.stamp(); + IntegerStamp stamp = (IntegerStamp) value.stamp(NodeView.DEFAULT); // the bytecode verifier doesn't check that the value is in the correct range if (stamp.lowerBound() < returnKind.getMinValue() || returnKind.getMaxValue() < stamp.upperBound()) { @@ -2480,7 +2482,7 @@ public class BytecodeParser implements GraphBuilderContext { JsrScope scope = currentBlock.getJsrScope(); int retAddress = scope.nextReturnAddress(); ConstantNode returnBciNode = getJsrConstant(retAddress); - LogicNode guard = IntegerEqualsNode.create(constantReflection, metaAccess, options, null, local, returnBciNode); + LogicNode guard = IntegerEqualsNode.create(constantReflection, metaAccess, options, null, local, returnBciNode, NodeView.DEFAULT); guard = graph.addOrUniqueWithInputs(guard); append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile)); if (!successor.getJsrScope().equals(scope.pop())) { @@ -3184,7 +3186,7 @@ public class BytecodeParser implements GraphBuilderContext { private void genConditionalForIf(BciBlock trueBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt, boolean genReturn) { ConstantNode trueValue = graph.unique(ConstantNode.forInt(trueBlockInt)); ConstantNode falseValue = graph.unique(ConstantNode.forInt(falseBlockInt)); - ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue); + ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue, NodeView.DEFAULT); if (conditionalNode.graph() == null) { conditionalNode = graph.addOrUniqueWithInputs(conditionalNode); } @@ -3716,7 +3718,7 @@ public class BytecodeParser implements GraphBuilderContext { } } - boolean nonNull = ((ObjectStamp) object.stamp()).nonNull(); + boolean nonNull = ((ObjectStamp) object.stamp(NodeView.DEFAULT)).nonNull(); if (castNode == null) { LogicNode condition = genUnique(createInstanceOfAllowNull(checkedType, object, null)); if (condition.isTautology()) { @@ -4174,7 +4176,8 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode value = frameState.pop(JavaKind.Int); int nofCases = bs.numberOfCases(); - double[] keyProbabilities = switchProbability(nofCases + 1, bci); + int nofCasesPlusDefault = nofCases + 1; + double[] keyProbabilities = switchProbability(nofCasesPlusDefault, bci); EconomicMap bciToBlockSuccessorIndex = EconomicMap.create(Equivalence.DEFAULT); for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { @@ -4184,11 +4187,11 @@ public class BytecodeParser implements GraphBuilderContext { ArrayList actualSuccessors = new ArrayList<>(); int[] keys = new int[nofCases]; - int[] keySuccessors = new int[nofCases + 1]; + int[] keySuccessors = new int[nofCasesPlusDefault]; int deoptSuccessorIndex = -1; int nextSuccessorIndex = 0; boolean constantValue = value.isConstant(); - for (int i = 0; i < nofCases + 1; i++) { + for (int i = 0; i < nofCasesPlusDefault; i++) { if (i < nofCases) { keys[i] = bs.keyAt(i); } @@ -4200,7 +4203,7 @@ public class BytecodeParser implements GraphBuilderContext { } keySuccessors[i] = deoptSuccessorIndex; } else { - int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i); + int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget(); SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); if (info.actualIndex < 0) { info.actualIndex = nextSuccessorIndex++; @@ -4209,6 +4212,48 @@ public class BytecodeParser implements GraphBuilderContext { keySuccessors[i] = info.actualIndex; } } + /* + * When the profile indicates a case is never taken, the above code will cause the case to + * deopt should it be subsequently encountered. However, the case may share code with + * another case that is taken according to the profile. + * + * For example: + * // @formatter:off + * switch (opcode) { + * case GOTO: + * case GOTO_W: { + * // emit goto code + * break; + * } + * } + * // @formatter:on + * + * The profile may indicate the GOTO_W case is never taken, and thus a deoptimization stub + * will be emitted. There might be optimization opportunity if additional branching based + * on opcode is within the case block. Specially, if there is only single case that + * reaches a target, we have better chance cutting out unused branches. Otherwise, + * it might be beneficial routing to the same code instead of deopting. + * + * The following code rewires deoptimization stub to existing resolved branch target if + * the target is connected by more than 1 cases. + */ + if (deoptSuccessorIndex >= 0) { + int[] connectedCases = new int[nextSuccessorIndex]; + for (int i = 0; i < nofCasesPlusDefault; i++) { + connectedCases[keySuccessors[i]]++; + } + + for (int i = 0; i < nofCasesPlusDefault; i++) { + if (keySuccessors[i] == deoptSuccessorIndex) { + int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget(); + SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); + int rewiredIndex = info.actualIndex; + if (rewiredIndex >= 0 && connectedCases[rewiredIndex] > 1) { + keySuccessors[i] = info.actualIndex; + } + } + } + } genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java index b924c25f85c..04b2c315ed4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java @@ -55,6 +55,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ProxyNode; @@ -460,7 +461,7 @@ public final class FrameStateBuilder implements SideEffectsState { } private ValuePhiNode createValuePhi(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) { - ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block)); + ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp(NodeView.DEFAULT).unrestricted(), block)); for (int i = 0; i < block.phiPredecessorCount(); i++) { phi.addInput(currentValue); } @@ -558,7 +559,7 @@ public final class FrameStateBuilder implements SideEffectsState { } assert !block.isPhiAtMerge(value) : "phi function for this block already created"; - ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(stampFromValue ? value.stamp() : value.stamp().unrestricted(), block)); + ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(stampFromValue ? value.stamp(NodeView.DEFAULT) : value.stamp(NodeView.DEFAULT).unrestricted(), block)); phi.addInput(value); return phi; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java index a69bf2d8059..25d05b83774 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.jtt.jdk; import org.graalvm.compiler.jtt.JTTTest; -import org.junit.Assume; import org.junit.Test; public class Unsafe_compareAndSwapNullCheck extends JTTTest { @@ -48,8 +47,6 @@ public class Unsafe_compareAndSwapNullCheck extends JTTTest { @Test public void run0() throws Throwable { - // GR-2921: Unsafe_compareAndSwapNullCheck test crashes on jdk9 - Assume.assumeTrue(Java8OrEarlier); runTest(getInitialOptions(), EMPTY, false, true, "test", null, 1L, 2L); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java index 38fdd263a6c..7b9add5daaf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java @@ -299,16 +299,23 @@ public class AMD64Move { @Def({REG}) protected AllocatableValue result; @Use({COMPOSITE, UNINITIALIZED}) protected AMD64AddressValue address; + private final OperandSize size; - public LeaOp(AllocatableValue result, AMD64AddressValue address) { + public LeaOp(AllocatableValue result, AMD64AddressValue address, OperandSize size) { super(TYPE); this.result = result; this.address = address; + this.size = size; } @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - masm.leaq(asRegister(result, AMD64Kind.QWORD), address.toAddress()); + if (size == OperandSize.QWORD) { + masm.leaq(asRegister(result, AMD64Kind.QWORD), address.toAddress()); + } else { + assert size == OperandSize.DWORD; + masm.lead(asRegister(result, AMD64Kind.DWORD), address.toAddress()); + } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java index b3f3bdd9440..5e4a5c513cd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java @@ -340,7 +340,7 @@ abstract class LIRIntrospection extends FieldIntrospection { private static boolean isPrintableAsciiString(byte[] array) { for (byte b : array) { char c = (char) b; - if (c != 0 && c < 0x20 && c > 0x7F) { + if (c != 0 && (c < 0x20 || c > 0x7F)) { return false; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java index 82665f59712..cb02e6653cb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java @@ -159,97 +159,101 @@ public class LinearScanLifetimeAnalysisPhase extends LinearScanAllocationPhase { intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops()); - // iterate all blocks - for (final AbstractBlockBase block : allocator.sortedBlocks()) { - try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) { + try { + // iterate all blocks + for (final AbstractBlockBase block : allocator.sortedBlocks()) { + try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) { - final BitSet liveGen = new BitSet(liveSize); - final BitSet liveKill = new BitSet(liveSize); + final BitSet liveGen = new BitSet(liveSize); + final BitSet liveKill = new BitSet(liveSize); - ArrayList instructions = allocator.getLIR().getLIRforBlock(block); - int numInst = instructions.size(); + ArrayList instructions = allocator.getLIR().getLIRforBlock(block); + int numInst = instructions.size(); - ValueConsumer useConsumer = (operand, mode, flags) -> { - if (isVariable(operand)) { - int operandNum = allocator.operandNumber(operand); - if (!liveKill.get(operandNum)) { - liveGen.set(operandNum); - if (debug.isLogEnabled()) { - debug.log("liveGen for operand %d(%s)", operandNum, operand); + ValueConsumer useConsumer = (operand, mode, flags) -> { + if (isVariable(operand)) { + int operandNum = allocator.operandNumber(operand); + if (!liveKill.get(operandNum)) { + liveGen.set(operandNum); + if (debug.isLogEnabled()) { + debug.log("liveGen for operand %d(%s)", operandNum, operand); + } + } + if (block.getLoop() != null) { + intervalInLoop.setBit(operandNum, block.getLoop().getIndex()); } } - if (block.getLoop() != null) { - intervalInLoop.setBit(operandNum, block.getLoop().getIndex()); - } - } - if (allocator.detailedAsserts) { - verifyInput(block, liveKill, operand); - } - }; - ValueConsumer stateConsumer = (operand, mode, flags) -> { - if (LinearScan.isVariableOrRegister(operand)) { - int operandNum = allocator.operandNumber(operand); - if (!liveKill.get(operandNum)) { - liveGen.set(operandNum); - if (debug.isLogEnabled()) { - debug.log("liveGen in state for operand %d(%s)", operandNum, operand); + if (allocator.detailedAsserts) { + verifyInput(block, liveKill, operand); + } + }; + ValueConsumer stateConsumer = (operand, mode, flags) -> { + if (LinearScan.isVariableOrRegister(operand)) { + int operandNum = allocator.operandNumber(operand); + if (!liveKill.get(operandNum)) { + liveGen.set(operandNum); + if (debug.isLogEnabled()) { + debug.log("liveGen in state for operand %d(%s)", operandNum, operand); + } } } - } - }; - ValueConsumer defConsumer = (operand, mode, flags) -> { - if (isVariable(operand)) { - int varNum = allocator.operandNumber(operand); - liveKill.set(varNum); - if (debug.isLogEnabled()) { - debug.log("liveKill for operand %d(%s)", varNum, operand); + }; + ValueConsumer defConsumer = (operand, mode, flags) -> { + if (isVariable(operand)) { + int varNum = allocator.operandNumber(operand); + liveKill.set(varNum); + if (debug.isLogEnabled()) { + debug.log("liveKill for operand %d(%s)", varNum, operand); + } + if (block.getLoop() != null) { + intervalInLoop.setBit(varNum, block.getLoop().getIndex()); + } } - if (block.getLoop() != null) { - intervalInLoop.setBit(varNum, block.getLoop().getIndex()); + + if (allocator.detailedAsserts) { + /* + * Fixed intervals are never live at block boundaries, so they need not + * be processed in live sets. Process them only in debug mode so that + * this can be checked + */ + verifyTemp(liveKill, operand); } + }; + + // iterate all instructions of the block + for (int j = 0; j < numInst; j++) { + final LIRInstruction op = instructions.get(j); + + try (Indent indent2 = debug.logAndIndent("handle op %d: %s", op.id(), op)) { + op.visitEachInput(useConsumer); + op.visitEachAlive(useConsumer); + /* + * Add uses of live locals from interpreter's point of view for proper + * debug information generation. + */ + op.visitEachState(stateConsumer); + op.visitEachTemp(defConsumer); + op.visitEachOutput(defConsumer); + } + } // end of instruction iteration + + BlockData blockSets = allocator.getBlockData(block); + blockSets.liveGen = liveGen; + blockSets.liveKill = liveKill; + blockSets.liveIn = new BitSet(liveSize); + blockSets.liveOut = new BitSet(liveSize); + + if (debug.isLogEnabled()) { + debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); + debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); } - if (allocator.detailedAsserts) { - /* - * Fixed intervals are never live at block boundaries, so they need not be - * processed in live sets. Process them only in debug mode so that this can - * be checked - */ - verifyTemp(liveKill, operand); - } - }; - - // iterate all instructions of the block - for (int j = 0; j < numInst; j++) { - final LIRInstruction op = instructions.get(j); - - try (Indent indent2 = debug.logAndIndent("handle op %d: %s", op.id(), op)) { - op.visitEachInput(useConsumer); - op.visitEachAlive(useConsumer); - /* - * Add uses of live locals from interpreter's point of view for proper debug - * information generation. - */ - op.visitEachState(stateConsumer); - op.visitEachTemp(defConsumer); - op.visitEachOutput(defConsumer); - } - } // end of instruction iteration - - BlockData blockSets = allocator.getBlockData(block); - blockSets.liveGen = liveGen; - blockSets.liveKill = liveKill; - blockSets.liveIn = new BitSet(liveSize); - blockSets.liveOut = new BitSet(liveSize); - - if (debug.isLogEnabled()) { - debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); - debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); } - - } - } // end of block iteration + } // end of block iteration + } catch (OutOfMemoryError oom) { + throw new PermanentBailoutException(oom, "Out-of-memory during live set allocation of size %d", liveSize); + } } private void verifyTemp(BitSet liveKill, Value operand) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java index 0aac4b7ecf8..d6b6de653a9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java @@ -76,7 +76,7 @@ public class ConstantTree extends PrintableDominatorOptimizationProblem getUsages() { if (usages == null) { - Collections.emptyList(); + return Collections.emptyList(); } return usages; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java index 6d27b6414dc..5c2683200e9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; @@ -70,7 +71,7 @@ public class BasicInductionVariable extends InductionVariable { @Override public Direction direction() { - Stamp stamp = rawStride.stamp(); + Stamp stamp = rawStride.stamp(NodeView.DEFAULT); if (stamp instanceof IntegerStamp) { IntegerStamp integerStamp = (IntegerStamp) stamp; Direction dir = null; @@ -140,27 +141,27 @@ public class BasicInductionVariable extends InductionVariable { @Override public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { - Stamp fromStamp = phi.stamp(); + Stamp fromStamp = phi.stamp(NodeView.DEFAULT); StructuredGraph graph = graph(); ValueNode stride = strideNode(); ValueNode initNode = this.initNode(); if (!fromStamp.isCompatible(stamp)) { - stride = IntegerConvertNode.convert(stride, stamp, graph()); - initNode = IntegerConvertNode.convert(initNode, stamp, graph()); + stride = IntegerConvertNode.convert(stride, stamp, graph(), NodeView.DEFAULT); + initNode = IntegerConvertNode.convert(initNode, stamp, graph(), NodeView.DEFAULT); } ValueNode maxTripCount = loop.counted().maxTripCountNode(assumePositiveTripCount); - if (!maxTripCount.stamp().isCompatible(stamp)) { - maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); + if (!maxTripCount.stamp(NodeView.DEFAULT).isCompatible(stamp)) { + maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph(), NodeView.DEFAULT); } return add(graph, mul(graph, stride, sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode); } @Override public ValueNode exitValueNode() { - Stamp stamp = phi.stamp(); + Stamp stamp = phi.stamp(NodeView.DEFAULT); ValueNode maxTripCount = loop.counted().maxTripCountNode(false); - if (!maxTripCount.stamp().isCompatible(stamp)) { - maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); + if (!maxTripCount.stamp(NodeView.DEFAULT).isCompatible(stamp)) { + maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph(), NodeView.DEFAULT); } return add(graph(), mul(graph(), strideNode(), maxTripCount), initNode()); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java index ae6bb412278..86a942eeda4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; @@ -69,7 +70,7 @@ public class CountedLoopInfo { public ValueNode maxTripCountNode(boolean assumePositive) { StructuredGraph graph = iv.valueNode().graph(); - Stamp stamp = iv.valueNode().stamp(); + Stamp stamp = iv.valueNode().stamp(NodeView.DEFAULT); ValueNode range = sub(graph, end, iv.initNode()); ValueNode oneDirection; @@ -84,7 +85,7 @@ public class CountedLoopInfo { } // round-away-from-zero divison: (range + stride -/+ 1) / stride ValueNode denominator = range; - if (!oneDirection.stamp().equals(iv.strideNode().stamp())) { + if (!oneDirection.stamp(NodeView.DEFAULT).equals(iv.strideNode().stamp(NodeView.DEFAULT))) { ValueNode subedRanged = sub(graph, range, oneDirection); denominator = add(graph, subedRanged, iv.strideNode()); } @@ -204,7 +205,7 @@ public class CountedLoopInfo { if (overflowGuard != null) { return overflowGuard; } - IntegerStamp stamp = (IntegerStamp) iv.valueNode().stamp(); + IntegerStamp stamp = (IntegerStamp) iv.valueNode().stamp(NodeView.DEFAULT); StructuredGraph graph = iv.valueNode().graph(); CompareNode cond; // we use a negated guard with a < condition to achieve a >= ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph); @@ -230,6 +231,6 @@ public class CountedLoopInfo { } public IntegerStamp getStamp() { - return (IntegerStamp) iv.valueNode().stamp(); + return (IntegerStamp) iv.valueNode().stamp(NodeView.DEFAULT); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedConvertedInductionVariable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedConvertedInductionVariable.java index dc0ef63febd..79a078496a7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedConvertedInductionVariable.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedConvertedInductionVariable.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.loop; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IntegerConvertNode; @@ -49,12 +50,12 @@ public class DerivedConvertedInductionVariable extends DerivedInductionVariable @Override public ValueNode initNode() { - return IntegerConvertNode.convert(base.initNode(), stamp, graph()); + return IntegerConvertNode.convert(base.initNode(), stamp, graph(), NodeView.DEFAULT); } @Override public ValueNode strideNode() { - return IntegerConvertNode.convert(base.strideNode(), stamp, graph()); + return IntegerConvertNode.convert(base.strideNode(), stamp, graph(), NodeView.DEFAULT); } @Override @@ -84,7 +85,7 @@ public class DerivedConvertedInductionVariable extends DerivedInductionVariable @Override public ValueNode exitValueNode() { - return IntegerConvertNode.convert(base.exitValueNode(), stamp, graph()); + return IntegerConvertNode.convert(base.exitValueNode(), stamp, graph(), NodeView.DEFAULT); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java index 33d0ed1636f..64aecebe331 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.loop.MathUtil.sub; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; @@ -90,14 +91,14 @@ public class DerivedOffsetInductionVariable extends DerivedInductionVariable { @Override public ValueNode strideNode() { if (value instanceof SubNode && base.valueNode() == value.getY()) { - return graph().addOrUniqueWithInputs(NegateNode.create(base.strideNode())); + return graph().addOrUniqueWithInputs(NegateNode.create(base.strideNode(), NodeView.DEFAULT)); } return base.strideNode(); } @Override public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { - return op(base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(offset, stamp, graph())); + return op(base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(offset, stamp, graph(), NodeView.DEFAULT)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedScaledInductionVariable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedScaledInductionVariable.java index 7d897981616..b85f0ea5df5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedScaledInductionVariable.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedScaledInductionVariable.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.loop.MathUtil.mul; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IntegerConvertNode; import org.graalvm.compiler.nodes.calc.NegateNode; @@ -45,7 +46,7 @@ public class DerivedScaledInductionVariable extends DerivedInductionVariable { public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, NegateNode value) { super(loop, base); - this.scale = ConstantNode.forIntegerStamp(value.stamp(), -1, value.graph()); + this.scale = ConstantNode.forIntegerStamp(value.stamp(NodeView.DEFAULT), -1, value.graph()); this.value = value; } @@ -60,7 +61,7 @@ public class DerivedScaledInductionVariable extends DerivedInductionVariable { @Override public Direction direction() { - Stamp stamp = scale.stamp(); + Stamp stamp = scale.stamp(NodeView.DEFAULT); if (stamp instanceof IntegerStamp) { IntegerStamp integerStamp = (IntegerStamp) stamp; if (integerStamp.isStrictlyPositive()) { @@ -104,7 +105,7 @@ public class DerivedScaledInductionVariable extends DerivedInductionVariable { @Override public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { - return mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph())); + return mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph(), NodeView.DEFAULT)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/InductionVariable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/InductionVariable.java index 2384ad832ca..d4edf5b69d3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/InductionVariable.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/InductionVariable.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.loop; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -93,7 +94,7 @@ public abstract class InductionVariable { * {@link CountedLoopInfo#isExactTripCount()} returns false for the containing loop. */ public ValueNode extremumNode() { - return extremumNode(false, valueNode().stamp()); + return extremumNode(false, valueNode().stamp(NodeView.DEFAULT)); } public abstract ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java index 79158e4d672..b0a2931db66 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java @@ -44,6 +44,7 @@ import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -188,7 +189,7 @@ public class LoopEx { if (!binary.isAssociative()) { continue; } - ValueNode result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY()); + ValueNode result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY(), NodeView.DEFAULT); if (result != binary) { if (!result.isAlive()) { assert !result.isDeleted(); @@ -259,8 +260,8 @@ public class LoopEx { if (!iv.isConstantStride() || Math.abs(iv.constantStride()) != 1) { return false; } - IntegerStamp initStamp = (IntegerStamp) iv.initNode().stamp(); - IntegerStamp limitStamp = (IntegerStamp) limit.stamp(); + IntegerStamp initStamp = (IntegerStamp) iv.initNode().stamp(NodeView.DEFAULT); + IntegerStamp limitStamp = (IntegerStamp) limit.stamp(NodeView.DEFAULT); if (iv.direction() == Direction.Up) { if (initStamp.upperBound() > limitStamp.lowerBound()) { return false; @@ -392,12 +393,12 @@ public class LoopEx { } else { boolean isValidConvert = op instanceof PiNode || op instanceof SignExtendNode; if (!isValidConvert && op instanceof ZeroExtendNode) { - IntegerStamp inputStamp = (IntegerStamp) ((ZeroExtendNode) op).getValue().stamp(); + IntegerStamp inputStamp = (IntegerStamp) ((ZeroExtendNode) op).getValue().stamp(NodeView.DEFAULT); isValidConvert = inputStamp.isPositive(); } if (isValidConvert) { - iv = new DerivedConvertedInductionVariable(loop, baseIv, op.stamp(), op); + iv = new DerivedConvertedInductionVariable(loop, baseIv, op.stamp(NodeView.DEFAULT), op); } } @@ -411,7 +412,7 @@ public class LoopEx { } private static ValueNode addSub(LoopEx loop, ValueNode op, ValueNode base) { - if (op.stamp() instanceof IntegerStamp && (op instanceof AddNode || op instanceof SubNode)) { + if (op.stamp(NodeView.DEFAULT) instanceof IntegerStamp && (op instanceof AddNode || op instanceof SubNode)) { BinaryArithmeticNode aritOp = (BinaryArithmeticNode) op; if (aritOp.getX() == base && loop.isOutsideLoop(aritOp.getY())) { return aritOp.getY(); @@ -434,7 +435,7 @@ public class LoopEx { if (op instanceof LeftShiftNode) { LeftShiftNode shift = (LeftShiftNode) op; if (shift.getX() == base && shift.getY().isConstant()) { - return ConstantNode.forIntegerStamp(base.stamp(), 1 << shift.getY().asJavaConstant().asInt(), base.graph()); + return ConstantNode.forIntegerStamp(base.stamp(NodeView.DEFAULT), 1 << shift.getY().asJavaConstant().asInt(), base.graph()); } } return null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java index 1a778623b34..9323ec4bb9f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodes.GuardProxyNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -460,7 +461,7 @@ public abstract class LoopFragment { if (newVpn != null) { PhiNode phi; if (vpn instanceof ValueProxyNode) { - phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(), merge)); + phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge)); } else if (vpn instanceof GuardProxyNode) { phi = graph.addWithoutUnique(new GuardPhiNode(merge)); } else { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java index a13ea7bbf08..8ae334b11d5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.SafepointNode; @@ -213,11 +214,11 @@ public class LoopFragmentInside extends LoopFragment { } long originalStride = unrollFactor == 1 ? iv.constantStride() : iv.constantStride() / unrollFactor; if (iv.direction() == InductionVariable.Direction.Up) { - ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(), unrollFactor * originalStride)); + ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * originalStride)); ValueNode newLimit = graph.addWithoutUnique(new SubNode(compareBound, aboveVal)); compareNode.replaceFirstInput(compareBound, newLimit); } else if (iv.direction() == InductionVariable.Direction.Down) { - ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(), unrollFactor * -originalStride)); + ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * -originalStride)); ValueNode newLimit = graph.addWithoutUnique(new AddNode(compareBound, aboveVal)); compareNode.replaceFirstInput(compareBound, newLimit); } @@ -391,7 +392,7 @@ public class LoopFragmentInside extends LoopFragment { private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, AbstractMergeNode merge) { PhiNode ret; if (phi instanceof ValuePhiNode) { - ret = new ValuePhiNode(phi.stamp(), merge); + ret = new ValuePhiNode(phi.stamp(NodeView.DEFAULT), merge); } else if (phi instanceof GuardPhiNode) { ret = new GuardPhiNode(merge); } else if (phi instanceof MemoryPhiNode) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java index 9c4333edd40..6a20d17faae 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java @@ -24,9 +24,11 @@ package org.graalvm.compiler.loop; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; +import org.graalvm.compiler.nodes.calc.FixedBinaryNode; import org.graalvm.compiler.nodes.calc.SignedDivNode; /** @@ -34,11 +36,11 @@ import org.graalvm.compiler.nodes.calc.SignedDivNode; */ public class MathUtil { private static boolean isConstantOne(ValueNode v1) { - return v1.isConstant() && v1.stamp() instanceof IntegerStamp && v1.asJavaConstant().asLong() == 1; + return v1.isConstant() && v1.stamp(NodeView.DEFAULT) instanceof IntegerStamp && v1.asJavaConstant().asLong() == 1; } private static boolean isConstantZero(ValueNode v1) { - return v1.isConstant() && v1.stamp() instanceof IntegerStamp && v1.asJavaConstant().asLong() == 0; + return v1.isConstant() && v1.stamp(NodeView.DEFAULT) instanceof IntegerStamp && v1.asJavaConstant().asLong() == 0; } public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { @@ -48,7 +50,7 @@ public class MathUtil { if (isConstantZero(v2)) { return v1; } - return BinaryArithmeticNode.add(graph, v1, v2); + return BinaryArithmeticNode.add(graph, v1, v2, NodeView.DEFAULT); } public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { @@ -58,22 +60,24 @@ public class MathUtil { if (isConstantOne(v2)) { return v1; } - return BinaryArithmeticNode.mul(graph, v1, v2); + return BinaryArithmeticNode.mul(graph, v1, v2, NodeView.DEFAULT); } public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { if (isConstantZero(v2)) { return v1; } - return BinaryArithmeticNode.sub(graph, v1, v2); + return BinaryArithmeticNode.sub(graph, v1, v2, NodeView.DEFAULT); } public static ValueNode divBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor) { if (isConstantOne(divisor)) { return dividend; } - SignedDivNode div = graph.add(new SignedDivNode(dividend, divisor)); - graph.addBeforeFixed(before, div); + ValueNode div = graph.addOrUniqueWithInputs(SignedDivNode.create(dividend, divisor, NodeView.DEFAULT)); + if (div instanceof FixedBinaryNode) { + graph.addBeforeFixed(before, (FixedBinaryNode) div); + } return div; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeProcessor.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeProcessor.java index 1d21ccbcab0..f1ee5d20db8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeProcessor.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo.processor/src/org/graalvm/compiler/nodeinfo/processor/GraphNodeProcessor.java @@ -103,7 +103,6 @@ public class GraphNodeProcessor extends AbstractProcessor { private void reportException(Kind kind, Element element, Throwable t) { StringWriter buf = new StringWriter(); t.printStackTrace(new PrintWriter(buf)); - buf.toString(); message(kind, element, "Exception thrown during processing: %s", buf.toString()); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java index 04832ecd1a3..756661318ff 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.test.GraphTest; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.options.OptionValues; @@ -67,52 +68,52 @@ public class IntegerStampTest extends GraphTest { @Test public void testBooleanConstant() { - assertEquals(IntegerStamp.create(32, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp()); - assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp()); + assertEquals(IntegerStamp.create(32, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp(NodeView.DEFAULT)); } @Test public void testByteConstant() { - assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp()); - assertEquals(IntegerStamp.create(32, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp()); - assertEquals(IntegerStamp.create(32, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp()); - assertEquals(IntegerStamp.create(32, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp()); - assertEquals(IntegerStamp.create(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp()); + assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp(NodeView.DEFAULT)); } @Test public void testShortConstant() { - assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp()); - assertEquals(IntegerStamp.create(32, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp()); - assertEquals(IntegerStamp.create(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp()); - assertEquals(IntegerStamp.create(32, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp()); - assertEquals(IntegerStamp.create(32, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp()); + assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp(NodeView.DEFAULT)); } @Test public void testCharConstant() { - assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp()); - assertEquals(IntegerStamp.create(32, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp()); - assertEquals(IntegerStamp.create(32, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp()); - assertEquals(IntegerStamp.create(32, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp()); + assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp(NodeView.DEFAULT)); } @Test public void testIntConstant() { - assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp()); - assertEquals(IntegerStamp.create(32, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp()); - assertEquals(IntegerStamp.create(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp()); - assertEquals(IntegerStamp.create(32, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp()); - assertEquals(IntegerStamp.create(32, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp()); + assertEquals(IntegerStamp.create(32, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(32, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp(NodeView.DEFAULT)); } @Test public void testLongConstant() { - assertEquals(IntegerStamp.create(64, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp()); - assertEquals(IntegerStamp.create(64, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp()); - assertEquals(IntegerStamp.create(64, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp()); - assertEquals(IntegerStamp.create(64, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp()); - assertEquals(IntegerStamp.create(64, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp()); + assertEquals(IntegerStamp.create(64, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(64, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(64, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(64, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp(NodeView.DEFAULT)); + assertEquals(IntegerStamp.create(64, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp(NodeView.DEFAULT)); } @Test diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/NegateNodeCanonicalizationTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/NegateNodeCanonicalizationTest.java index d5061078b07..3f7a0b75253 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/NegateNodeCanonicalizationTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/NegateNodeCanonicalizationTest.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.options.OptionValues; @@ -57,7 +58,7 @@ public class NegateNodeCanonicalizationTest { for (byte i : a) { ConstantNode node = ConstantNode.forByte(i, graph); JavaConstant expected = JavaConstant.forInt(-i); - assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp()).getNeg().foldConstant(node.asConstant())); + assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp(NodeView.DEFAULT)).getNeg().foldConstant(node.asConstant())); } } @@ -67,7 +68,7 @@ public class NegateNodeCanonicalizationTest { for (char i : a) { ConstantNode node = ConstantNode.forChar(i, graph); JavaConstant expected = JavaConstant.forInt(-i); - assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp()).getNeg().foldConstant(node.asConstant())); + assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp(NodeView.DEFAULT)).getNeg().foldConstant(node.asConstant())); } } @@ -77,7 +78,7 @@ public class NegateNodeCanonicalizationTest { for (short i : a) { ConstantNode node = ConstantNode.forShort(i, graph); JavaConstant expected = JavaConstant.forInt(-i); - assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp()).getNeg().foldConstant(node.asConstant())); + assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp(NodeView.DEFAULT)).getNeg().foldConstant(node.asConstant())); } } @@ -87,7 +88,7 @@ public class NegateNodeCanonicalizationTest { for (int i : a) { ConstantNode node = ConstantNode.forInt(i, graph); JavaConstant expected = JavaConstant.forInt(-i); - assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp()).getNeg().foldConstant(node.asConstant())); + assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp(NodeView.DEFAULT)).getNeg().foldConstant(node.asConstant())); } } @@ -97,7 +98,7 @@ public class NegateNodeCanonicalizationTest { for (long i : a) { ConstantNode node = ConstantNode.forLong(i, graph); JavaConstant expected = JavaConstant.forLong(-i); - assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp()).getNeg().foldConstant(node.asConstant())); + assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp(NodeView.DEFAULT)).getNeg().foldConstant(node.asConstant())); } } @@ -107,7 +108,7 @@ public class NegateNodeCanonicalizationTest { for (float i : a) { ConstantNode node = ConstantNode.forFloat(i, graph); JavaConstant expected = JavaConstant.forFloat(-i); - assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp()).getNeg().foldConstant(node.asConstant())); + assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp(NodeView.DEFAULT)).getNeg().foldConstant(node.asConstant())); } } @@ -117,7 +118,7 @@ public class NegateNodeCanonicalizationTest { for (double i : a) { ConstantNode node = ConstantNode.forDouble(i, graph); JavaConstant expected = JavaConstant.forDouble(-i); - assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp()).getNeg().foldConstant(node.asConstant())); + assertEquals(expected, ArithmeticOpTable.forStamp(node.stamp(NodeView.DEFAULT)).getNeg().foldConstant(node.asConstant())); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampDoubleToLongTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampDoubleToLongTest.java index f2575f20505..e68101e8336 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampDoubleToLongTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampDoubleToLongTest.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.ValueNode; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -77,9 +79,9 @@ public class ReinterpretStampDoubleToLongTest extends ReinterpretStampTest { @Test public void run() { ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp)); - ReinterpretNode reinterpret = new ReinterpretNode(JavaKind.Long, param); + ValueNode reinterpret = ReinterpretNode.create(JavaKind.Long, param, NodeView.DEFAULT); - IntegerStamp resultStamp = (IntegerStamp) reinterpret.stamp(); + IntegerStamp resultStamp = (IntegerStamp) reinterpret.stamp(NodeView.DEFAULT); Assert.assertEquals(Long.SIZE, resultStamp.getBits()); for (long result : interestingLongs) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampFloatToIntTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampFloatToIntTest.java index b24285d7a00..fb7f6115761 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampFloatToIntTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampFloatToIntTest.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.ValueNode; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -77,10 +79,10 @@ public class ReinterpretStampFloatToIntTest extends ReinterpretStampTest { @Test public void run() { ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp)); - ReinterpretNode reinterpret = new ReinterpretNode(JavaKind.Int, param); + ValueNode reinterpret = ReinterpretNode.create(JavaKind.Int, param, NodeView.DEFAULT); reinterpret.inferStamp(); - IntegerStamp resultStamp = (IntegerStamp) reinterpret.stamp(); + IntegerStamp resultStamp = (IntegerStamp) reinterpret.stamp(NodeView.DEFAULT); Assert.assertEquals(Integer.SIZE, resultStamp.getBits()); for (int result : interestingInts) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampIntToFloatTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampIntToFloatTest.java index b4fd7b48011..510680f0934 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampIntToFloatTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampIntToFloatTest.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.ValueNode; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,10 +70,10 @@ public class ReinterpretStampIntToFloatTest extends ReinterpretStampTest { @Test public void run() { ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp)); - ReinterpretNode reinterpret = new ReinterpretNode(JavaKind.Float, param); + ValueNode reinterpret = ReinterpretNode.create(JavaKind.Float, param, NodeView.DEFAULT); reinterpret.inferStamp(); - FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(); + FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(NodeView.DEFAULT); Assert.assertEquals(Float.SIZE, resultStamp.getBits()); for (int input : interestingInts) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampLongToDoubleTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampLongToDoubleTest.java index 08642f3bd14..b18389e9118 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampLongToDoubleTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ReinterpretStampLongToDoubleTest.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.ValueNode; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,10 +70,10 @@ public class ReinterpretStampLongToDoubleTest extends ReinterpretStampTest { @Test public void run() { ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp)); - ReinterpretNode reinterpret = new ReinterpretNode(JavaKind.Double, param); + ValueNode reinterpret = ReinterpretNode.create(JavaKind.Double, param, NodeView.DEFAULT); reinterpret.inferStamp(); - FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(); + FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(NodeView.DEFAULT); Assert.assertEquals(Double.SIZE, resultStamp.getBits()); for (long input : interestingLongs) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java index 6f9a420af59..3b7b0f0f9a1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java @@ -68,7 +68,7 @@ public abstract class CompressionNode extends UnaryNode implements ConvertNode, @Override public Stamp foldStamp(Stamp newStamp) { - assert newStamp.isCompatible(getValue().stamp()); + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); return mkStamp(newStamp); } @@ -124,7 +124,8 @@ public abstract class CompressionNode extends UnaryNode implements ConvertNode, } ConstantNode constant = (ConstantNode) forValue; - return ConstantNode.forConstant(stamp(), convert(constant.getValue(), tool.getConstantReflection()), constant.getStableDimension(), constant.isDefaultStable(), tool.getMetaAccess()); + return ConstantNode.forConstant(stamp(NodeView.DEFAULT), convert(constant.getValue(), tool.getConstantReflection()), constant.getStableDimension(), constant.isDefaultStable(), + tool.getMetaAccess()); } else if (forValue instanceof CompressionNode) { CompressionNode other = (CompressionNode) forValue; if (op != other.op && encoding.equals(other.encoding)) { @@ -137,8 +138,8 @@ public abstract class CompressionNode extends UnaryNode implements ConvertNode, @Override public void generate(NodeLIRBuilderTool gen) { boolean nonNull; - if (value.stamp() instanceof AbstractObjectStamp) { - nonNull = StampTool.isPointerNonNull(value.stamp()); + if (value.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp) { + nonNull = StampTool.isPointerNonNull(value.stamp(NodeView.DEFAULT)); } else { // metaspace pointers are never null nonNull = true; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java index 4dd797fe32c..87ee52b0800 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java @@ -134,7 +134,7 @@ public final class ConstantNode extends FloatingNode implements LIRLowerable { @Override public void generate(NodeLIRBuilderTool gen) { - LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp()); + LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); if (onlyUsedInVirtualState()) { gen.setResult(this, new ConstantValue(kind, value)); } else { @@ -525,7 +525,7 @@ public final class ConstantNode extends FloatingNode implements LIRLowerable { @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Name) { - return super.toString(Verbosity.Name) + "(" + value.toValueString() + ", " + stamp().unrestricted().toString() + ")"; + return super.toString(Verbosity.Name) + "(" + value.toValueString() + ", " + stamp(NodeView.DEFAULT).unrestricted().toString() + ")"; } else { return super.toString(verbosity); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EntryProxyNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EntryProxyNode.java index 95d3d17beae..838a11c3dda 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EntryProxyNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EntryProxyNode.java @@ -44,7 +44,7 @@ public final class EntryProxyNode extends FloatingNode implements ValueProxy { @Input ValueNode value; public EntryProxyNode(ValueNode value, EntryMarkerNode proxyPoint) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp(NodeView.DEFAULT).unrestricted()); this.value = value; this.proxyPoint = proxyPoint; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java index 1f3f2629e48..9b08cbaffaf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java @@ -310,7 +310,7 @@ public class GraphDecoder { @Input(InputType.Unchecked) Node proxyPoint; public ProxyPlaceholder(ValueNode value, MergeNode proxyPoint) { - super(TYPE, value.stamp()); + super(TYPE, value.stamp(NodeView.DEFAULT)); this.value = value; this.proxyPoint = proxyPoint; } @@ -868,7 +868,7 @@ public class GraphDecoder { /* Now we have two different values, so we need to create a phi node. */ PhiNode phi; if (proxy instanceof ValueProxyNode) { - phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(), merge)); + phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge)); } else if (proxy instanceof GuardProxyNode) { phi = graph.addWithoutUnique(new GuardPhiNode(merge)); } else { @@ -1630,7 +1630,7 @@ class LoopDetector implements Runnable { List loopBeginPhis = new ArrayList<>(mergePhis.size()); for (int i = 0; i < mergePhis.size(); i++) { PhiNode mergePhi = mergePhis.get(i); - PhiNode loopBeginPhi = graph.addWithoutUnique(new ValuePhiNode(mergePhi.stamp(), loopBegin)); + PhiNode loopBeginPhi = graph.addWithoutUnique(new ValuePhiNode(mergePhi.stamp(NodeView.DEFAULT), loopBegin)); mergePhi.replaceAtUsages(loopBeginPhi); /* * The first input of the new phi function is the original phi function, for the one @@ -1793,7 +1793,7 @@ class LoopDetector implements Runnable { assert irreducibleLoopHandler.header.phis().isEmpty(); /* The new phi function for the loop variable. */ - loopVariablePhi = graph.addWithoutUnique(new ValuePhiNode(explosionHeadValue.stamp().unrestricted(), irreducibleLoopHandler.header)); + loopVariablePhi = graph.addWithoutUnique(new ValuePhiNode(explosionHeadValue.stamp(NodeView.DEFAULT).unrestricted(), irreducibleLoopHandler.header)); for (int i = 0; i < irreducibleLoopHandler.header.phiPredecessorCount(); i++) { loopVariablePhi.addInput(explosionHeadValue); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java index 42a2e0a277e..2f0ba9b6def 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java @@ -53,7 +53,7 @@ public final class GuardedValueNode extends FloatingGuardedNode implements LIRLo @Input ValueNode object; public GuardedValueNode(ValueNode object, GuardingNode guard) { - super(TYPE, object.stamp(), guard); + super(TYPE, object.stamp(NodeView.DEFAULT), guard); this.object = object; } @@ -70,7 +70,7 @@ public final class GuardedValueNode extends FloatingGuardedNode implements LIRLo @Override public boolean inferStamp() { - return updateStamp(object().stamp()); + return updateStamp(object().stamp(NodeView.DEFAULT)); } @Override @@ -84,10 +84,10 @@ public final class GuardedValueNode extends FloatingGuardedNode implements LIRLo @Override public Node canonical(CanonicalizerTool tool) { if (getGuard() == null) { - if (stamp().equals(object().stamp())) { + if (stamp(NodeView.DEFAULT).equals(object().stamp(NodeView.DEFAULT))) { return object(); } else { - return PiNode.create(object(), stamp()); + return PiNode.create(object(), stamp(NodeView.DEFAULT)); } } return this; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java index 616b1de0ac1..ff7428f7799 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java @@ -65,7 +65,6 @@ import org.graalvm.util.EconomicMap; import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PrimitiveConstant; @@ -238,7 +237,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL if (this.trueSuccessorProbability < probabilityB) { // Reordering of those two if statements is beneficial from the point of view of // their probabilities. - if (prepareForSwap(tool.getConstantReflection(), condition(), nextIf.condition())) { + if (prepareForSwap(tool, condition(), nextIf.condition())) { // Reordering is allowed from (if1 => begin => if2) to (if2 => begin => if1). assert intermediateBegin.next() == nextIf; AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor(); @@ -267,19 +266,19 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL } } - private boolean isUnboxedFrom(MetaAccessProvider meta, ValueNode x, ValueNode src) { + private boolean isUnboxedFrom(MetaAccessProvider meta, NodeView view, ValueNode x, ValueNode src) { if (x == src) { return true; } else if (x instanceof UnboxNode) { - return isUnboxedFrom(meta, ((UnboxNode) x).getValue(), src); + return isUnboxedFrom(meta, view, ((UnboxNode) x).getValue(), src); } else if (x instanceof PiNode) { PiNode pi = (PiNode) x; - return isUnboxedFrom(meta, pi.getOriginalNode(), src); + return isUnboxedFrom(meta, view, pi.getOriginalNode(), src); } else if (x instanceof LoadFieldNode) { LoadFieldNode load = (LoadFieldNode) x; ResolvedJavaType integerType = meta.lookupJavaType(Integer.class); - if (load.getValue().stamp().javaType(meta).equals(integerType)) { - return isUnboxedFrom(meta, load.getValue(), src); + if (load.getValue().stamp(view).javaType(meta).equals(integerType)) { + return isUnboxedFrom(meta, view, load.getValue(), src); } else { return false; } @@ -321,7 +320,8 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL ResolvedJavaType integerType = meta.lookupJavaType(Integer.class); // At least one argument for reference equal must be a boxed primitive. - if (!x.stamp().javaType(meta).equals(integerType) && !y.stamp().javaType(meta).equals(integerType)) { + NodeView view = NodeView.from(tool); + if (!x.stamp(view).javaType(meta).equals(integerType) && !y.stamp(view).javaType(meta).equals(integerType)) { return false; } @@ -366,7 +366,8 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL continue; } IntegerEqualsNode equals = (IntegerEqualsNode) fixed.condition(); - if ((isUnboxedFrom(meta, equals.getX(), x) && isUnboxedFrom(meta, equals.getY(), y)) || (isUnboxedFrom(meta, equals.getX(), y) && isUnboxedFrom(meta, equals.getY(), x))) { + if ((isUnboxedFrom(meta, view, equals.getX(), x) && isUnboxedFrom(meta, view, equals.getY(), y)) || + (isUnboxedFrom(meta, view, equals.getX(), y) && isUnboxedFrom(meta, view, equals.getY(), x))) { unboxCheck = fixed; } } @@ -406,7 +407,8 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL ValueNode falseValue = phi.valueAt(falseEnd); ValueNode trueValue = phi.valueAt(trueEnd); - ValueNode result = ConditionalNode.canonicalizeConditional(condition, trueValue, falseValue, phi.stamp()); + NodeView view = NodeView.from(tool); + ValueNode result = ConditionalNode.canonicalizeConditional(condition, trueValue, falseValue, phi.stamp(view), view); if (result != null) { /* * canonicalizeConditional returns possibly new nodes so add them to the graph. @@ -477,8 +479,9 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL private boolean checkForUnsignedCompare(SimplifierTool tool) { assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages(); if (condition() instanceof IntegerLessThanNode) { + NodeView view = NodeView.from(tool); IntegerLessThanNode lessThan = (IntegerLessThanNode) condition(); - Constant y = lessThan.getY().stamp().asConstant(); + Constant y = lessThan.getY().stamp(view).asConstant(); if (y instanceof PrimitiveConstant && ((PrimitiveConstant) y).asLong() == 0 && falseSuccessor().next() instanceof IfNode) { IfNode ifNode2 = (IfNode) falseSuccessor().next(); if (ifNode2.condition() instanceof IntegerLessThanNode) { @@ -490,7 +493,8 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL * Convert x >= 0 && x < positive which is represented as !(x < 0) && x < * into an unsigned compare. */ - if (lessThan2.getX() == lessThan.getX() && lessThan2.getY().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.getY().stamp()).isPositive() && + if (lessThan2.getX() == lessThan.getX() && lessThan2.getY().stamp(view) instanceof IntegerStamp && + ((IntegerStamp) lessThan2.getY().stamp(view)).isPositive() && sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) { below = graph().unique(new IntegerBelowNode(lessThan2.getX(), lessThan2.getY())); // swap direction @@ -506,7 +510,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL */ JavaConstant positive = lessThan2.getX().asJavaConstant(); if (positive != null && positive.asLong() > 0 && positive.asLong() < positive.getJavaKind().getMaxValue()) { - ConstantNode newLimit = ConstantNode.forIntegerStamp(lessThan2.getX().stamp(), positive.asLong() + 1, graph()); + ConstantNode newLimit = ConstantNode.forIntegerStamp(lessThan2.getX().stamp(view), positive.asLong() + 1, graph()); below = graph().unique(new IntegerBelowNode(lessThan.getX(), newLimit)); } } @@ -574,7 +578,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL return false; } - private static boolean prepareForSwap(ConstantReflectionProvider constantReflection, LogicNode a, LogicNode b) { + private static boolean prepareForSwap(SimplifierTool tool, LogicNode a, LogicNode b) { DebugContext debug = a.getDebug(); if (a instanceof InstanceOfNode) { InstanceOfNode instanceOfA = (InstanceOfNode) a; @@ -625,13 +629,13 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL } } else if (conditionA == Condition.EQ && conditionB == Condition.EQ) { boolean canSwap = false; - if ((compareA.getX() == compareB.getX() && valuesDistinct(constantReflection, compareA.getY(), compareB.getY()))) { + if ((compareA.getX() == compareB.getX() && valuesDistinct(tool, compareA.getY(), compareB.getY()))) { canSwap = true; - } else if ((compareA.getX() == compareB.getY() && valuesDistinct(constantReflection, compareA.getY(), compareB.getX()))) { + } else if ((compareA.getX() == compareB.getY() && valuesDistinct(tool, compareA.getY(), compareB.getX()))) { canSwap = true; - } else if ((compareA.getY() == compareB.getX() && valuesDistinct(constantReflection, compareA.getX(), compareB.getY()))) { + } else if ((compareA.getY() == compareB.getX() && valuesDistinct(tool, compareA.getX(), compareB.getY()))) { canSwap = true; - } else if ((compareA.getY() == compareB.getY() && valuesDistinct(constantReflection, compareA.getX(), compareB.getX()))) { + } else if ((compareA.getY() == compareB.getY() && valuesDistinct(tool, compareA.getX(), compareB.getX()))) { canSwap = true; } @@ -646,16 +650,17 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL return false; } - private static boolean valuesDistinct(ConstantReflectionProvider constantReflection, ValueNode a, ValueNode b) { + private static boolean valuesDistinct(SimplifierTool tool, ValueNode a, ValueNode b) { if (a.isConstant() && b.isConstant()) { - Boolean equal = constantReflection.constantEquals(a.asConstant(), b.asConstant()); + Boolean equal = tool.getConstantReflection().constantEquals(a.asConstant(), b.asConstant()); if (equal != null) { return !equal.booleanValue(); } } - Stamp stampA = a.stamp(); - Stamp stampB = b.stamp(); + NodeView view = NodeView.from(tool); + Stamp stampA = a.stamp(view); + Stamp stampB = b.stamp(view); return stampA.alwaysDistinct(stampB); } @@ -691,7 +696,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL } else if (distinct == 1) { ValueNode trueValue = singlePhi.valueAt(trueEnd); ValueNode falseValue = singlePhi.valueAt(falseEnd); - ValueNode conditional = canonicalizeConditionalCascade(trueValue, falseValue); + ValueNode conditional = canonicalizeConditionalCascade(tool, trueValue, falseValue); if (conditional != null) { singlePhi.setValueAt(trueEnd, conditional); removeThroughFalseBranch(tool, merge); @@ -710,7 +715,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL if (trueValue == falseValue) { value = trueValue; } else { - value = canonicalizeConditionalCascade(trueValue, falseValue); + value = canonicalizeConditionalCascade(tool, trueValue, falseValue); if (value == null) { return false; } @@ -745,7 +750,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL } } - private ValueNode canonicalizeConditionalCascade(ValueNode trueValue, ValueNode falseValue) { + private ValueNode canonicalizeConditionalCascade(SimplifierTool tool, ValueNode trueValue, ValueNode falseValue) { if (trueValue.getStackKind() != falseValue.getStackKind()) { return null; } @@ -796,8 +801,9 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL } if (lessThan != null) { assert equals != null; + NodeView view = NodeView.from(tool); if ((lessThan.getX() == equals.getX() && lessThan.getY() == equals.getY()) || (lessThan.getX() == equals.getY() && lessThan.getY() == equals.getX())) { - return graph().unique(new NormalizeCompareNode(lessThan.getX(), lessThan.getY(), conditional.trueValue().stamp().getStackKind(), false)); + return graph().unique(new NormalizeCompareNode(lessThan.getX(), lessThan.getY(), conditional.trueValue().stamp(view).getStackKind(), false)); } } } @@ -1287,10 +1293,11 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL GraphUtil.killCFG(end); } else { // Need a new phi in case the frame state is used by more than the merge being - // removed + // removed. + NodeView view = NodeView.from(tool); AbstractMergeNode newMerge = graph().add(new MergeNode()); PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); - PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(), newMerge)); + PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(view), newMerge)); for (EndNode end : ends) { newPhi.addInput(phiValues.get(end)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java index cf475f2f7bb..0c7da53f3e4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java @@ -342,7 +342,7 @@ public final class LoopBeginNode extends AbstractMergeNode implements IterableNo for (int i = 0; i < phi.valueCount(); i++) { ValueNode input = phi.valueAt(i); long increment = NO_INCREMENT; - if (input != null && input instanceof AddNode && input.stamp() instanceof IntegerStamp) { + if (input != null && input instanceof AddNode && input.stamp(NodeView.DEFAULT) instanceof IntegerStamp) { AddNode add = (AddNode) input; if (add.getX() == phi && add.getY().isConstant()) { increment = add.getY().asJavaConstant().asLong(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NodeView.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NodeView.java new file mode 100644 index 00000000000..636f2af87c4 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NodeView.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 2017, 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.graalvm.compiler.nodes; + +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; + +/** + * Interface that overrides properties of a node, such as the node's stamp. + * + * This interface allows richer canonicalizations when the current compilation context can provide a + * narrower stamp than the one stored in the node itself. One such example is performing + * canonicalization late in the compilation, when the nodes are already scheduled, and benefit from + * additional stamp information from conditional checks in branches. + * + * For example, in the following code, offset + i can be canonicalized once it is + * scheduled into the branch: + * + *

+ * public void update(int offset, int i) {
+ *     if (i == 0) {
+ *         array[offset + i];
+ *     }
+ * }
+ * 
+ */ +public interface NodeView { + + NodeView DEFAULT = new Default(); + + class Default implements NodeView { + @Override + public Stamp stamp(ValueNode node) { + return node.stamp; + } + } + + /** + * Return a view-specific stamp of the node. + * + * This stamp must be more specific than the default stamp. + */ + Stamp stamp(ValueNode node); + + static NodeView from(CanonicalizerTool tool) { + if (tool instanceof NodeView) { + return (NodeView) tool; + } + return DEFAULT; + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PhiNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PhiNode.java index 2d517d17ba5..410b82d6b00 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PhiNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PhiNode.java @@ -152,7 +152,7 @@ public abstract class PhiNode extends FloatingNode implements Canonicalizable { public void addInput(ValueNode x) { assert !(x instanceof ValuePhiNode) || ((ValuePhiNode) x).merge() instanceof LoopBeginNode || ((ValuePhiNode) x).merge() != this.merge(); - assert !(this instanceof ValuePhiNode) || x.stamp().isCompatible(stamp()); + assert !(this instanceof ValuePhiNode) || x.stamp(NodeView.DEFAULT).isCompatible(stamp(NodeView.DEFAULT)); values().add(x); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java index 2b0207c53b5..6fd619b78a5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java @@ -76,7 +76,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual super(c, stamp, guard); this.object = object; this.piStamp = stamp; - assert piStamp.isCompatible(object.stamp()) : "Object stamp not compatible to piStamp"; + assert piStamp.isCompatible(object.stamp(NodeView.DEFAULT)) : "Object stamp not compatible to piStamp"; inferStamp(); } @@ -89,11 +89,12 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual } public PiNode(ValueNode object, ValueNode guard) { - this(object, AbstractPointerStamp.pointerNonNull(object.stamp()), guard); + this(object, AbstractPointerStamp.pointerNonNull(object.stamp(NodeView.DEFAULT)), guard); } public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { - this(object, StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), nonNull || StampTool.isPointerNonNull(object.stamp()))); + this(object, StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), + nonNull || StampTool.isPointerNonNull(object.stamp(NodeView.DEFAULT)))); } public static ValueNode create(ValueNode object, Stamp stamp) { @@ -113,7 +114,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual } public static ValueNode create(ValueNode object, ValueNode guard) { - Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp()); + Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp(NodeView.DEFAULT)); ValueNode value = canonical(object, stamp, (GuardingNode) guard); if (value != null) { return value; @@ -123,7 +124,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual @SuppressWarnings("unused") public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ValueNode guard) { - Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp()); + Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp(NodeView.DEFAULT)); ValueNode value = canonical(object, stamp, (GuardingNode) guard); if (value == null) { value = new PiNode(object, stamp, guard); @@ -134,7 +135,8 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual @SuppressWarnings("unused") public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { - Stamp stamp = StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), nonNull || StampTool.isPointerNonNull(object.stamp())); + Stamp stamp = StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), + nonNull || StampTool.isPointerNonNull(object.stamp(NodeView.DEFAULT))); ValueNode value = canonical(object, stamp, null); if (value == null) { value = new PiNode(object, stamp); @@ -165,7 +167,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual } private Stamp computeStamp() { - return piStamp.improveWith(object().stamp()); + return piStamp.improveWith(object().stamp(NodeView.DEFAULT)); } @Override @@ -181,10 +183,10 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual public static ValueNode canonical(ValueNode object, Stamp stamp, GuardingNode guard) { // Use most up to date stamp. - Stamp computedStamp = stamp.improveWith(object.stamp()); + Stamp computedStamp = stamp.improveWith(object.stamp(NodeView.DEFAULT)); // The pi node does not give any additional information => skip it. - if (computedStamp.equals(object.stamp())) { + if (computedStamp.equals(object.stamp(NodeView.DEFAULT))) { return object; } @@ -192,14 +194,14 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual // Try to merge the pi node with a load node. if (object instanceof ReadNode) { ReadNode readNode = (ReadNode) object; - readNode.setStamp(readNode.stamp().improveWith(stamp)); + readNode.setStamp(readNode.stamp(NodeView.DEFAULT).improveWith(stamp)); return readNode; } } else { for (Node n : guard.asNode().usages()) { if (n instanceof PiNode) { PiNode otherPi = (PiNode) n; - if (object == otherPi.object() && computedStamp.equals(otherPi.stamp())) { + if (object == otherPi.object() && computedStamp.equals(otherPi.stamp(NodeView.DEFAULT))) { /* * Two PiNodes with the same guard and same result, so return the one with * the more precise piStamp. @@ -217,7 +219,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual @Override public Node canonical(CanonicalizerTool tool) { - Node value = canonical(object(), stamp(), getGuard()); + Node value = canonical(object(), stamp(NodeView.DEFAULT), getGuard()); if (value != null) { return value; } @@ -232,7 +234,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual public void setOriginalNode(ValueNode newNode) { this.updateUsages(object, newNode); this.object = newNode; - assert piStamp.isCompatible(object.stamp()) : "New object stamp not compatible to piStamp"; + assert piStamp.isCompatible(object.stamp(NodeView.DEFAULT)) : "New object stamp not compatible to piStamp"; } /** diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 2255a228221..8db681571ed 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -360,9 +360,9 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { ValueNode result = returnNode.result(); if (result != null) { if (returnStamp == null) { - returnStamp = result.stamp(); + returnStamp = result.stamp(NodeView.DEFAULT); } else { - returnStamp = returnStamp.meet(result.stamp()); + returnStamp = returnStamp.meet(result.stamp(NodeView.DEFAULT)); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java index 8dae4d637b3..e2e0b575384 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java @@ -56,8 +56,8 @@ public abstract class ValueNode extends org.graalvm.compiler.graph.Node implemen this.stamp = stamp; } - public final Stamp stamp() { - return stamp; + public final Stamp stamp(NodeView view) { + return view.stamp(this); } public final void setStamp(Stamp stamp) { @@ -99,7 +99,7 @@ public abstract class ValueNode extends org.graalvm.compiler.graph.Node implemen } public final JavaKind getStackKind() { - return stamp().getStackKind(); + return stamp(NodeView.DEFAULT).getStackKind(); } /** @@ -197,9 +197,9 @@ public abstract class ValueNode extends org.graalvm.compiler.graph.Node implemen private boolean checkReplaceAtUsagesInvariants(Node other) { assert other == null || other instanceof ValueNode; - if (this.hasUsages() && !this.stamp().isEmpty() && !(other instanceof PhiNode) && other != null) { - assert ((ValueNode) other).stamp().getClass() == stamp().getClass() : "stamp have to be of same class"; - boolean morePrecise = ((ValueNode) other).stamp().join(stamp()).equals(((ValueNode) other).stamp()); + if (this.hasUsages() && !this.stamp(NodeView.DEFAULT).isEmpty() && !(other instanceof PhiNode) && other != null) { + assert ((ValueNode) other).stamp(NodeView.DEFAULT).getClass() == stamp(NodeView.DEFAULT).getClass() : "stamp have to be of same class"; + boolean morePrecise = ((ValueNode) other).stamp(NodeView.DEFAULT).join(stamp(NodeView.DEFAULT)).equals(((ValueNode) other).stamp(NodeView.DEFAULT)); assert morePrecise : "stamp can only get more precise " + toString(Verbosity.All) + " " + other.toString(Verbosity.All); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java index 8a60c072cdd..978df0e4c9c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java @@ -105,11 +105,11 @@ public class ValuePhiNode extends PhiNode implements ArrayLengthProvider { for (ValueNode input : values()) { assert input != null; if (s == null) { - s = input.stamp(); + s = input.stamp(NodeView.DEFAULT); } else { - if (!s.isCompatible(input.stamp())) { + if (!s.isCompatible(input.stamp(NodeView.DEFAULT))) { fail("Phi Input Stamps are not compatible. Phi:%s inputs:%s", this, - CollectionsUtil.mapAndJoin(values(), x -> x.toString() + ":" + x.stamp(), ", ")); + CollectionsUtil.mapAndJoin(values(), x -> x.toString() + ":" + x.stamp(NodeView.DEFAULT), ", ")); } } } @@ -118,7 +118,7 @@ public class ValuePhiNode extends PhiNode implements ArrayLengthProvider { @Override protected String valueDescription() { - return stamp().unrestricted().toString(); + return stamp(NodeView.DEFAULT).unrestricted().toString(); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java index 413e9060a0b..0e30b466866 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java @@ -41,7 +41,7 @@ public final class ValueProxyNode extends ProxyNode implements Canonicalizable, private final boolean loopPhiProxy; public ValueProxyNode(ValueNode value, LoopExitNode loopExit) { - super(TYPE, value.stamp(), loopExit); + super(TYPE, value.stamp(NodeView.DEFAULT), loopExit); this.value = value; loopPhiProxy = loopExit.loopBegin().isPhiAtMerge(value); } @@ -53,7 +53,7 @@ public final class ValueProxyNode extends ProxyNode implements Canonicalizable, @Override public boolean inferStamp() { - return updateStamp(value.stamp()); + return updateStamp(value.stamp(NodeView.DEFAULT)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AbsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AbsNode.java index 7c46a5ceaa6..18a3a6dd876 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AbsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AbsNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -46,6 +47,23 @@ public final class AbsNode extends UnaryArithmeticNode implements Arithmeti super(TYPE, ArithmeticOpTable::getAbs, x); } + public static ValueNode create(ValueNode value, NodeView view) { + ValueNode synonym = findSynonym(value, view); + if (synonym != null) { + return synonym; + } + return new NegateNode(value); + } + + protected static ValueNode findSynonym(ValueNode forValue, NodeView view) { + ArithmeticOpTable.UnaryOp absOp = ArithmeticOpTable.forStamp(forValue.stamp(view)).getAbs(); + ValueNode synonym = UnaryArithmeticNode.findSynonym(forValue, absOp); + if (synonym != null) { + return synonym; + } + return null; + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { ValueNode ret = super.canonical(tool, forValue); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java index 778bed510cc..dbf2fb13a9d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -51,21 +52,21 @@ public class AddNode extends BinaryArithmeticNode implements NarrowableArit super(c, ArithmeticOpTable::getAdd, x, y); } - public static ValueNode create(ValueNode x, ValueNode y) { - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getAdd(); - Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); - ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getAdd(); + Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); if (tryConstantFold != null) { return tryConstantFold; } if (x.isConstant() && !y.isConstant()) { - return canonical(null, op, y, x); + return canonical(null, op, y, x, view); } else { - return canonical(null, op, x, y); + return canonical(null, op, x, y, view); } } - private static ValueNode canonical(AddNode addNode, BinaryOp op, ValueNode forX, ValueNode forY) { + private static ValueNode canonical(AddNode addNode, BinaryOp op, ValueNode forX, ValueNode forY, NodeView view) { AddNode self = addNode; boolean associative = op.isAssociative(); if (associative) { @@ -91,16 +92,16 @@ public class AddNode extends BinaryArithmeticNode implements NarrowableArit } if (associative && self != null) { // canonicalize expressions like "(a + 1) + 2" - ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY); + ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY, view); if (reassociated != self) { return reassociated; } } } if (forX instanceof NegateNode) { - return BinaryArithmeticNode.sub(forY, ((NegateNode) forX).getValue()); + return BinaryArithmeticNode.sub(forY, ((NegateNode) forX).getValue(), view); } else if (forY instanceof NegateNode) { - return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue()); + return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue(), view); } if (self == null) { self = (AddNode) new AddNode(forX, forY).maybeCommuteInputs(); @@ -125,7 +126,8 @@ public class AddNode extends BinaryArithmeticNode implements NarrowableArit return new AddNode(forY, forX); } BinaryOp op = getOp(forX, forY); - return canonical(this, op, forX, forY); + NodeView view = NodeView.from(tool); + return canonical(this, op, forX, forY, view); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java index f97dbb7210d..e6c8231f10b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -51,14 +52,14 @@ public final class AndNode extends BinaryArithmeticNode implements Narrowab super(TYPE, ArithmeticOpTable::getAnd, x, y); } - public static ValueNode create(ValueNode x, ValueNode y) { - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getAnd(); - Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); - ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getAnd(); + Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); if (tryConstantFold != null) { return tryConstantFold; } - return canonical(null, op, stamp, x, y); + return canonical(null, op, stamp, x, y, view); } @Override @@ -68,10 +69,11 @@ public final class AndNode extends BinaryArithmeticNode implements Narrowab return ret; } - return canonical(this, getOp(forX, forY), stamp(), forX, forY); + NodeView view = NodeView.from(tool); + return canonical(this, getOp(forX, forY), stamp(view), forX, forY, view); } - private static ValueNode canonical(AndNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY) { + private static ValueNode canonical(AndNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return forX; } @@ -96,17 +98,17 @@ public final class AndNode extends BinaryArithmeticNode implements Narrowab return new ZeroExtendNode(ext.getValue(), ext.getResultBits()); } } - IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp xStamp = (IntegerStamp) forX.stamp(view); if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) { // No bits are set which are outside the mask, so the mask will have no effect. return forX; } } - return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY); + return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); } if (forX instanceof NotNode && forY instanceof NotNode) { - return new NotNode(OrNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue())); + return new NotNode(OrNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue(), view)); } return self != null ? self : new AndNode(forX, forY).maybeCommuteInputs(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java index 7593daecd74..84853e52dd7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java @@ -41,6 +41,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ArithmeticOperation; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; @@ -60,13 +61,13 @@ public abstract class BinaryArithmeticNode extends BinaryNode implements Ari protected final SerializableBinaryFunction getOp; protected BinaryArithmeticNode(NodeClass> c, SerializableBinaryFunction getOp, ValueNode x, ValueNode y) { - super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), y.stamp()), x, y); + super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp(NodeView.DEFAULT))).foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), x, y); this.getOp = getOp; } protected final BinaryOp getOp(ValueNode forX, ValueNode forY) { - ArithmeticOpTable table = ArithmeticOpTable.forStamp(forX.stamp()); - assert table.equals(ArithmeticOpTable.forStamp(forY.stamp())); + ArithmeticOpTable table = ArithmeticOpTable.forStamp(forX.stamp(NodeView.DEFAULT)); + assert table.equals(ArithmeticOpTable.forStamp(forY.stamp(NodeView.DEFAULT))); return getOp.apply(table); } @@ -81,14 +82,16 @@ public abstract class BinaryArithmeticNode extends BinaryNode implements Ari @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode result = tryConstantFold(getOp(forX, forY), forX, forY, stamp()); + NodeView view = NodeView.from(tool); + ValueNode result = tryConstantFold(getOp(forX, forY), forX, forY, stamp(view), view); if (result != null) { return result; } return this; } - public static ConstantNode tryConstantFold(BinaryOp op, ValueNode forX, ValueNode forY, Stamp stamp) { + @SuppressWarnings("unused") + public static ConstantNode tryConstantFold(BinaryOp op, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { if (forX.isConstant() && forY.isConstant()) { Constant ret = op.foldConstant(forX.asConstant(), forY.asConstant()); if (ret != null) { @@ -100,32 +103,32 @@ public abstract class BinaryArithmeticNode extends BinaryNode implements Ari @Override public Stamp foldStamp(Stamp stampX, Stamp stampY) { - assert stampX.isCompatible(x.stamp()) && stampY.isCompatible(y.stamp()); + assert stampX.isCompatible(x.stamp(NodeView.DEFAULT)) && stampY.isCompatible(y.stamp(NodeView.DEFAULT)); return getArithmeticOp().foldStamp(stampX, stampY); } - public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.addOrUniqueWithInputs(AddNode.create(v1, v2)); + public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { + return graph.addOrUniqueWithInputs(AddNode.create(v1, v2, view)); } - public static ValueNode add(ValueNode v1, ValueNode v2) { - return AddNode.create(v1, v2); + public static ValueNode add(ValueNode v1, ValueNode v2, NodeView view) { + return AddNode.create(v1, v2, view); } - public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.addOrUniqueWithInputs(MulNode.create(v1, v2)); + public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { + return graph.addOrUniqueWithInputs(MulNode.create(v1, v2, view)); } - public static ValueNode mul(ValueNode v1, ValueNode v2) { - return MulNode.create(v1, v2); + public static ValueNode mul(ValueNode v1, ValueNode v2, NodeView view) { + return MulNode.create(v1, v2, view); } - public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.addOrUniqueWithInputs(SubNode.create(v1, v2)); + public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { + return graph.addOrUniqueWithInputs(SubNode.create(v1, v2, view)); } - public static ValueNode sub(ValueNode v1, ValueNode v2) { - return SubNode.create(v1, v2); + public static ValueNode sub(ValueNode v1, ValueNode v2, NodeView view) { + return SubNode.create(v1, v2, view); } private enum ReassociateMatch { @@ -193,7 +196,7 @@ public abstract class BinaryArithmeticNode extends BinaryNode implements Ari * @param forY * @param forX */ - public static ValueNode reassociate(BinaryArithmeticNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) { + public static ValueNode reassociate(BinaryArithmeticNode node, NodePredicate criterion, ValueNode forX, ValueNode forY, NodeView view) { assert node.getOp(forX, forY).isAssociative(); ReassociateMatch match1 = findReassociate(node, criterion); if (match1 == null) { @@ -239,21 +242,21 @@ public abstract class BinaryArithmeticNode extends BinaryNode implements Ari if (node instanceof AddNode || node instanceof SubNode) { ValueNode associated; if (invertM1) { - associated = BinaryArithmeticNode.sub(m2, m1); + associated = BinaryArithmeticNode.sub(m2, m1, view); } else if (invertM2) { - associated = BinaryArithmeticNode.sub(m1, m2); + associated = BinaryArithmeticNode.sub(m1, m2, view); } else { - associated = BinaryArithmeticNode.add(m1, m2); + associated = BinaryArithmeticNode.add(m1, m2, view); } if (invertA) { - return BinaryArithmeticNode.sub(associated, a); + return BinaryArithmeticNode.sub(associated, a, view); } if (aSub) { - return BinaryArithmeticNode.sub(a, associated); + return BinaryArithmeticNode.sub(a, associated, view); } - return BinaryArithmeticNode.add(a, associated); + return BinaryArithmeticNode.add(a, associated, view); } else if (node instanceof MulNode) { - return BinaryArithmeticNode.mul(a, AddNode.mul(m1, m2)); + return BinaryArithmeticNode.mul(a, AddNode.mul(m1, m2, view), view); } else if (node instanceof AndNode) { return new AndNode(a, new AndNode(m1, m2)); } else if (node instanceof OrNode) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryNode.java index 3e45aa760f1..52cf1a00fef 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryNode.java @@ -26,6 +26,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; /** @@ -73,7 +74,7 @@ public abstract class BinaryNode extends FloatingNode implements Canonicalizable @Override public boolean inferStamp() { - return updateStamp(foldStamp(getX().stamp(), getY().stamp())); + return updateStamp(foldStamp(getX().stamp(NodeView.DEFAULT), getY().stamp(NodeView.DEFAULT))); } /** diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java index 55437cd2de4..14e102dc243 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -91,7 +92,8 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical return null; } - public static LogicNode tryConstantFoldPrimitive(Condition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue) { + @SuppressWarnings("unused") + public static LogicNode tryConstantFoldPrimitive(Condition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue, NodeView view) { if (forX.asConstant() instanceof PrimitiveConstant && forY.asConstant() instanceof PrimitiveConstant) { return LogicConstantNode.forBoolean(condition.foldCondition((PrimitiveConstant) forX.asConstant(), (PrimitiveConstant) forY.asConstant(), unorderedIsTrue)); } @@ -110,27 +112,27 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical public abstract static class CompareOp { public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, - boolean unorderedIsTrue, ValueNode forX, ValueNode forY) { + boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { LogicNode constantCondition = tryConstantFold(condition, forX, forY, constantReflection, unorderedIsTrue); if (constantCondition != null) { return constantCondition; } LogicNode result; if (forX.isConstant()) { - if ((result = canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, forX.asConstant(), forY, true, unorderedIsTrue)) != null) { + if ((result = canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, forX.asConstant(), forY, true, unorderedIsTrue, view)) != null) { return result; } } else if (forY.isConstant()) { - if ((result = canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, forY.asConstant(), forX, false, unorderedIsTrue)) != null) { + if ((result = canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, forY.asConstant(), forX, false, unorderedIsTrue, view)) != null) { return result; } } else if (forX instanceof ConvertNode && forY instanceof ConvertNode) { ConvertNode convertX = (ConvertNode) forX; ConvertNode convertY = (ConvertNode) forY; - if (convertX.preservesOrder(condition) && convertY.preservesOrder(condition) && convertX.getValue().stamp().isCompatible(convertY.getValue().stamp())) { + if (convertX.preservesOrder(condition) && convertY.preservesOrder(condition) && convertX.getValue().stamp(view).isCompatible(convertY.getValue().stamp(view))) { boolean supported = true; - if (convertX.getValue().stamp() instanceof IntegerStamp) { - IntegerStamp intStamp = (IntegerStamp) convertX.getValue().stamp(); + if (convertX.getValue().stamp(view) instanceof IntegerStamp) { + IntegerStamp intStamp = (IntegerStamp) convertX.getValue().stamp(view); supported = smallestCompareWidth != null && intStamp.getBits() >= smallestCompareWidth; } @@ -141,7 +143,7 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical // of the value. return null; } - return duplicateModified(convertX.getValue(), convertY.getValue(), unorderedIsTrue); + return duplicateModified(convertX.getValue(), convertY.getValue(), unorderedIsTrue, view); } } } @@ -149,11 +151,11 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical } protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue) { + Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { if (nonConstant instanceof ConditionalNode) { return optimizeConditional(constant, (ConditionalNode) nonConstant, constantReflection, mirrored ? condition.mirror() : condition, unorderedIsTrue); } else if (nonConstant instanceof NormalizeCompareNode) { - return optimizeNormalizeCompare(constantReflection, metaAccess, options, smallestCompareWidth, constant, (NormalizeCompareNode) nonConstant, mirrored); + return optimizeNormalizeCompare(constantReflection, metaAccess, options, smallestCompareWidth, constant, (NormalizeCompareNode) nonConstant, mirrored, view); } else if (nonConstant instanceof ConvertNode) { ConvertNode convert = (ConvertNode) nonConstant; boolean multiUsage = (convert.asNode().hasMoreThanOneUsage() && convert.getValue().hasExactlyOneUsage()); @@ -164,18 +166,18 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical } boolean supported = true; - if (convert.getValue().stamp() instanceof IntegerStamp) { - IntegerStamp intStamp = (IntegerStamp) convert.getValue().stamp(); + if (convert.getValue().stamp(view) instanceof IntegerStamp) { + IntegerStamp intStamp = (IntegerStamp) convert.getValue().stamp(view); supported = smallestCompareWidth != null && intStamp.getBits() > smallestCompareWidth; } if (supported) { - ConstantNode newConstant = canonicalConvertConstant(constantReflection, metaAccess, options, condition, convert, constant); + ConstantNode newConstant = canonicalConvertConstant(constantReflection, metaAccess, options, condition, convert, constant, view); if (newConstant != null) { if (mirrored) { - return duplicateModified(newConstant, convert.getValue(), unorderedIsTrue); + return duplicateModified(newConstant, convert.getValue(), unorderedIsTrue, view); } else { - return duplicateModified(convert.getValue(), newConstant, unorderedIsTrue); + return duplicateModified(convert.getValue(), newConstant, unorderedIsTrue, view); } } } @@ -185,7 +187,7 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical } private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Condition condition, - ConvertNode convert, Constant constant) { + ConvertNode convert, Constant constant, NodeView view) { if (convert.preservesOrder(condition, constant, constantReflection)) { Constant reverseConverted = convert.reverse(constant, constantReflection); if (reverseConverted != null && convert.convert(reverseConverted, constantReflection).equals(constant)) { @@ -193,7 +195,7 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical // We always want uncompressed constants return null; } - return ConstantNode.forConstant(convert.getValue().stamp(), reverseConverted, metaAccess); + return ConstantNode.forConstant(convert.getValue().stamp(view), reverseConverted, metaAccess); } } return null; @@ -201,7 +203,7 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical @SuppressWarnings("unused") protected LogicNode optimizeNormalizeCompare(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { + Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored, NodeView view) { throw new GraalError("NormalizeCompareNode connected to %s (%s %s %s)", this, constant, normalizeNode, mirrored); } @@ -230,71 +232,71 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical return null; } - protected abstract LogicNode duplicateModified(ValueNode newW, ValueNode newY, boolean unorderedIsTrue); + protected abstract LogicNode duplicateModified(ValueNode newW, ValueNode newY, boolean unorderedIsTrue, NodeView view); } - public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { - LogicNode result = createCompareNode(condition, x, y, constantReflection); + public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { + LogicNode result = createCompareNode(condition, x, y, constantReflection, view); return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result); } - public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { + public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { assert x.getStackKind() == y.getStackKind(); assert condition.isCanonical(); assert !x.getStackKind().isNumericFloat(); LogicNode comparison; if (condition == Condition.EQ) { - if (x.stamp() instanceof AbstractObjectStamp) { - comparison = ObjectEqualsNode.create(x, y, constantReflection); - } else if (x.stamp() instanceof AbstractPointerStamp) { - comparison = PointerEqualsNode.create(x, y); + if (x.stamp(view) instanceof AbstractObjectStamp) { + comparison = ObjectEqualsNode.create(x, y, constantReflection, view); + } else if (x.stamp(view) instanceof AbstractPointerStamp) { + comparison = PointerEqualsNode.create(x, y, view); } else { assert x.getStackKind().isNumericInteger(); - comparison = IntegerEqualsNode.create(x, y); + comparison = IntegerEqualsNode.create(x, y, view); } } else if (condition == Condition.LT) { assert x.getStackKind().isNumericInteger(); - comparison = IntegerLessThanNode.create(x, y); + comparison = IntegerLessThanNode.create(x, y, view); } else { assert condition == Condition.BT; assert x.getStackKind().isNumericInteger(); - comparison = IntegerBelowNode.create(x, y); + comparison = IntegerBelowNode.create(x, y, view); } return comparison; } public static LogicNode createCompareNode(StructuredGraph graph, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, ValueNode x, ValueNode y) { - LogicNode result = createCompareNode(constantReflection, metaAccess, options, smallestCompareWidth, condition, x, y); + Condition condition, ValueNode x, ValueNode y, NodeView view) { + LogicNode result = createCompareNode(constantReflection, metaAccess, options, smallestCompareWidth, condition, x, y, view); return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result); } public static LogicNode createCompareNode(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, ValueNode x, ValueNode y) { + Condition condition, ValueNode x, ValueNode y, NodeView view) { assert x.getStackKind() == y.getStackKind(); assert condition.isCanonical(); assert !x.getStackKind().isNumericFloat(); LogicNode comparison; if (condition == Condition.EQ) { - if (x.stamp() instanceof AbstractObjectStamp) { + if (x.stamp(view) instanceof AbstractObjectStamp) { assert smallestCompareWidth == null; - comparison = ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y); - } else if (x.stamp() instanceof AbstractPointerStamp) { - comparison = PointerEqualsNode.create(x, y); + comparison = ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, view); + } else if (x.stamp(view) instanceof AbstractPointerStamp) { + comparison = PointerEqualsNode.create(x, y, view); } else { assert x.getStackKind().isNumericInteger(); - comparison = IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y); + comparison = IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view); } } else if (condition == Condition.LT) { assert x.getStackKind().isNumericInteger(); - comparison = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y); + comparison = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view); } else { assert condition == Condition.BT; assert x.getStackKind().isNumericInteger(); - comparison = IntegerBelowNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y); + comparison = IntegerBelowNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view); } return comparison; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java index c06eea37c9b..bff140ebc63 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -55,8 +56,8 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab public static final NodeClass TYPE = NodeClass.create(ConditionalNode.class); @Input(InputType.Condition) LogicNode condition; - @Input ValueNode trueValue; - @Input ValueNode falseValue; + @Input(InputType.Value) ValueNode trueValue; + @Input(InputType.Value) ValueNode falseValue; public LogicNode condition() { return condition; @@ -67,23 +68,23 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab } public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { - super(TYPE, trueValue.stamp().meet(falseValue.stamp())); - assert trueValue.stamp().isCompatible(falseValue.stamp()); + super(TYPE, trueValue.stamp(NodeView.DEFAULT).meet(falseValue.stamp(NodeView.DEFAULT))); + assert trueValue.stamp(NodeView.DEFAULT).isCompatible(falseValue.stamp(NodeView.DEFAULT)); this.condition = condition; this.trueValue = trueValue; this.falseValue = falseValue; } - public static ValueNode create(LogicNode condition) { - return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph())); + public static ValueNode create(LogicNode condition, NodeView view) { + return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph()), view); } - public static ValueNode create(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { - ValueNode synonym = findSynonym(condition, trueValue, falseValue); + public static ValueNode create(LogicNode condition, ValueNode trueValue, ValueNode falseValue, NodeView view) { + ValueNode synonym = findSynonym(condition, trueValue, falseValue, view); if (synonym != null) { return synonym; } - ValueNode result = canonicalizeConditional(condition, trueValue, falseValue, trueValue.stamp().meet(falseValue.stamp())); + ValueNode result = canonicalizeConditional(condition, trueValue, falseValue, trueValue.stamp(view).meet(falseValue.stamp(view)), view); if (result != null) { return result; } @@ -92,7 +93,7 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab @Override public boolean inferStamp() { - Stamp valueStamp = trueValue.stamp().meet(falseValue.stamp()); + Stamp valueStamp = trueValue.stamp(NodeView.DEFAULT).meet(falseValue.stamp(NodeView.DEFAULT)); if (condition instanceof IntegerLessThanNode) { IntegerLessThanNode lessThan = (IntegerLessThanNode) condition; if (lessThan.getX() == trueValue && lessThan.getY() == falseValue) { @@ -130,12 +131,13 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab @Override public ValueNode canonical(CanonicalizerTool tool) { - ValueNode synonym = findSynonym(condition, trueValue(), falseValue()); + NodeView view = NodeView.from(tool); + ValueNode synonym = findSynonym(condition, trueValue(), falseValue(), view); if (synonym != null) { return synonym; } - ValueNode result = canonicalizeConditional(condition, trueValue(), falseValue(), stamp); + ValueNode result = canonicalizeConditional(condition, trueValue(), falseValue(), stamp, view); if (result != null) { return result; } @@ -143,7 +145,7 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab return this; } - public static ValueNode canonicalizeConditional(LogicNode condition, ValueNode trueValue, ValueNode falseValue, Stamp stamp) { + public static ValueNode canonicalizeConditional(LogicNode condition, ValueNode trueValue, ValueNode falseValue, Stamp stamp, NodeView view) { if (trueValue == falseValue) { return trueValue; } @@ -156,12 +158,12 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab } } - if (trueValue.stamp() instanceof IntegerStamp) { + if (trueValue.stamp(view) instanceof IntegerStamp) { // check if the conditional is redundant if (condition instanceof IntegerLessThanNode) { IntegerLessThanNode lessThan = (IntegerLessThanNode) condition; - IntegerStamp falseValueStamp = (IntegerStamp) falseValue.stamp(); - IntegerStamp trueValueStamp = (IntegerStamp) trueValue.stamp(); + IntegerStamp falseValueStamp = (IntegerStamp) falseValue.stamp(view); + IntegerStamp trueValueStamp = (IntegerStamp) trueValue.stamp(view); if (lessThan.getX() == trueValue && lessThan.getY() == falseValue) { // return "x" for "x < y ? x : y" in case that we know "x <= y" if (trueValueStamp.upperBound() <= falseValueStamp.lowerBound()) { @@ -182,25 +184,25 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab long constFalseValue = falseValue.asJavaConstant().asLong(); if (condition instanceof IntegerEqualsNode) { IntegerEqualsNode equals = (IntegerEqualsNode) condition; - if (equals.getY().isConstant() && equals.getX().stamp() instanceof IntegerStamp) { - IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp(); + if (equals.getY().isConstant() && equals.getX().stamp(view) instanceof IntegerStamp) { + IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp(view); if (equalsXStamp.upMask() == 1) { long equalsY = equals.getY().asJavaConstant().asLong(); if (equalsY == 0) { if (constTrueValue == 0 && constFalseValue == 1) { // return x when: x == 0 ? 0 : 1; - return IntegerConvertNode.convertUnsigned(equals.getX(), stamp); + return IntegerConvertNode.convertUnsigned(equals.getX(), stamp, view); } else if (constTrueValue == 1 && constFalseValue == 0) { // negate a boolean value via xor - return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp); + return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(view), 1), view), stamp, view); } } else if (equalsY == 1) { if (constTrueValue == 1 && constFalseValue == 0) { // return x when: x == 1 ? 1 : 0; - return IntegerConvertNode.convertUnsigned(equals.getX(), stamp); + return IntegerConvertNode.convertUnsigned(equals.getX(), stamp, view); } else if (constTrueValue == 0 && constFalseValue == 1) { // negate a boolean value via xor - return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp); + return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(view), 1), view), stamp, view); } } } @@ -211,10 +213,10 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab // (value & 1) == 1 ? 1 : 0 IntegerTestNode integerTestNode = (IntegerTestNode) condition; if (integerTestNode.getY().isConstant()) { - assert integerTestNode.getX().stamp() instanceof IntegerStamp; + assert integerTestNode.getX().stamp(view) instanceof IntegerStamp; long testY = integerTestNode.getY().asJavaConstant().asLong(); if (testY == 1 && constTrueValue == 0 && constFalseValue == 1) { - return IntegerConvertNode.convertUnsigned(AndNode.create(integerTestNode.getX(), integerTestNode.getY()), stamp); + return IntegerConvertNode.convertUnsigned(AndNode.create(integerTestNode.getX(), integerTestNode.getY(), view), stamp, view); } } } @@ -231,7 +233,7 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab if (trueValue instanceof AddNode) { AddNode add = (AddNode) trueValue; if (add.getX() == falseValue) { - int bits = ((IntegerStamp) trueValue.stamp()).getBits(); + int bits = ((IntegerStamp) trueValue.stamp(NodeView.DEFAULT)).getBits(); ValueNode shift = new RightShiftNode(lt.getX(), ConstantNode.forIntegerBits(32, bits - 1)); ValueNode and = new AndNode(shift, add.getY()); return new AddNode(add.getX(), and); @@ -245,10 +247,10 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab return null; } - private static ValueNode findSynonym(ValueNode condition, ValueNode trueValue, ValueNode falseValue) { + private static ValueNode findSynonym(ValueNode condition, ValueNode trueValue, ValueNode falseValue, NodeView view) { if (condition instanceof LogicNegationNode) { LogicNegationNode negated = (LogicNegationNode) condition; - return ConditionalNode.create(negated.getValue(), falseValue, trueValue); + return ConditionalNode.create(negated.getValue(), falseValue, trueValue, view); } if (condition instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition; @@ -267,6 +269,6 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab } public ConditionalNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { - this(createCompareNode(graph, condition, x, y, null)); + this(createCompareNode(graph, condition, x, y, null, NodeView.DEFAULT)); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatConvertNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatConvertNode.java index 25a82292cb4..450fa2a782e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatConvertNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatConvertNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -65,8 +66,8 @@ public final class FloatConvertNode extends UnaryArithmeticNode this.op = op; } - public static ValueNode create(FloatConvert op, ValueNode input) { - ValueNode synonym = findSynonym(input, ArithmeticOpTable.forStamp(input.stamp()).getFloatConvert(op)); + public static ValueNode create(FloatConvert op, ValueNode input, NodeView view) { + ValueNode synonym = findSynonym(input, ArithmeticOpTable.forStamp(input.stamp(view)).getFloatConvert(op)); if (synonym != null) { return synonym; } @@ -84,7 +85,7 @@ public final class FloatConvertNode extends UnaryArithmeticNode @Override public Constant reverse(Constant c, ConstantReflectionProvider constantReflection) { - FloatConvertOp reverse = ArithmeticOpTable.forStamp(stamp()).getFloatConvert(op.reverse()); + FloatConvertOp reverse = ArithmeticOpTable.forStamp(stamp(NodeView.DEFAULT)).getFloatConvert(op.reverse()); return reverse.foldConstant(c); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatDivNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatDivNode.java index 195241a9c2a..0f2c081fea5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatDivNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatDivNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -53,10 +54,10 @@ public class FloatDivNode extends BinaryArithmeticNode
{ assert stamp instanceof FloatStamp; } - public static ValueNode create(ValueNode x, ValueNode y) { - BinaryOp
op = ArithmeticOpTable.forStamp(x.stamp()).getDiv(); - Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); - ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + BinaryOp
op = ArithmeticOpTable.forStamp(x.stamp(view)).getDiv(); + Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); if (tryConstantFold != null) { return tryConstantFold; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java index 871973aa2b2..09b7072d31b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; @@ -50,12 +51,12 @@ public final class FloatEqualsNode extends CompareNode implements BinaryCommutat public FloatEqualsNode(ValueNode x, ValueNode y) { super(TYPE, Condition.EQ, false, x, y); - assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp : x.stamp() + " " + y.stamp(); - assert x.stamp().isCompatible(y.stamp()); + assert x.stamp(NodeView.DEFAULT) instanceof FloatStamp && y.stamp(NodeView.DEFAULT) instanceof FloatStamp : x.stamp(NodeView.DEFAULT) + " " + y.stamp(NodeView.DEFAULT); + assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)); } - public static LogicNode create(ValueNode x, ValueNode y) { - LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false); + public static LogicNode create(ValueNode x, ValueNode y, NodeView view) { + LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false, view); if (result != null) { return result; } else { @@ -64,18 +65,18 @@ public final class FloatEqualsNode extends CompareNode implements BinaryCommutat } public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - ValueNode x, ValueNode y) { - LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y); + ValueNode x, ValueNode y, NodeView view) { + LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y, view); if (value != null) { return value; } - return create(x, y); + return create(x, y, view); } @Override public boolean isIdentityComparison() { - FloatStamp xStamp = (FloatStamp) x.stamp(); - FloatStamp yStamp = (FloatStamp) y.stamp(); + FloatStamp xStamp = (FloatStamp) x.stamp(NodeView.DEFAULT); + FloatStamp yStamp = (FloatStamp) y.stamp(NodeView.DEFAULT); /* * If both stamps have at most one 0.0 and it's the same 0.0 then this is an identity * comparison. FloatStamp isn't careful about tracking the presence of -0.0 so assume that @@ -87,7 +88,8 @@ public final class FloatEqualsNode extends CompareNode implements BinaryCommutat @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, unorderedIsTrue, forX, forY); + NodeView view = NodeView.from(tool); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, unorderedIsTrue, forX, forY, view); if (value != null) { return value; } @@ -98,13 +100,13 @@ public final class FloatEqualsNode extends CompareNode implements BinaryCommutat @Override public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, - boolean unorderedIsTrue, ValueNode forX, ValueNode forY) { - LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY); + boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { + LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); if (result != null) { return result; } - Stamp xStampGeneric = forX.stamp(); - Stamp yStampGeneric = forY.stamp(); + Stamp xStampGeneric = forX.stamp(view); + Stamp yStampGeneric = forY.stamp(view); if (xStampGeneric instanceof FloatStamp && yStampGeneric instanceof FloatStamp) { FloatStamp xStamp = (FloatStamp) xStampGeneric; FloatStamp yStamp = (FloatStamp) yStampGeneric; @@ -118,10 +120,10 @@ public final class FloatEqualsNode extends CompareNode implements BinaryCommutat } @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue) { - if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) { + if (newX.stamp(view) instanceof FloatStamp && newY.stamp(view) instanceof FloatStamp) { return new FloatEqualsNode(newX, newY); - } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { + } else if (newX.stamp(view) instanceof IntegerStamp && newY.stamp(view) instanceof IntegerStamp) { return new IntegerEqualsNode(newX, newY); } throw GraalError.shouldNotReachHere(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java index 2f6666bab4f..8b1885ff9bd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; @@ -49,12 +50,12 @@ public final class FloatLessThanNode extends CompareNode { public FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) { super(TYPE, Condition.LT, unorderedIsTrue, x, y); - assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp; - assert x.stamp().isCompatible(y.stamp()); + assert x.stamp(NodeView.DEFAULT) instanceof FloatStamp && y.stamp(NodeView.DEFAULT) instanceof FloatStamp; + assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)); } - public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue) { - LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.LT, x, y, unorderedIsTrue); + public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) { + LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.LT, x, y, unorderedIsTrue, view); if (result != null) { return result; } @@ -62,17 +63,18 @@ public final class FloatLessThanNode extends CompareNode { } public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - ValueNode x, ValueNode y, boolean unorderedIsTrue) { - LogicNode result = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.LT, unorderedIsTrue, x, y); + ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) { + LogicNode result = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.LT, unorderedIsTrue, x, y, view); if (result != null) { return result; } - return create(x, y, unorderedIsTrue); + return create(x, y, unorderedIsTrue, view); } @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.LT, unorderedIsTrue, forX, forY); + NodeView view = NodeView.from(tool); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.LT, unorderedIsTrue, forX, forY, view); if (value != null) { return value; } @@ -83,8 +85,8 @@ public final class FloatLessThanNode extends CompareNode { @Override public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, - boolean unorderedIsTrue, ValueNode forX, ValueNode forY) { - LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY); + boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { + LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); if (result != null) { return result; } @@ -95,10 +97,10 @@ public final class FloatLessThanNode extends CompareNode { } @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue) { - if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) { + if (newX.stamp(NodeView.DEFAULT) instanceof FloatStamp && newY.stamp(NodeView.DEFAULT) instanceof FloatStamp) { return new FloatLessThanNode(newX, newY, unorderedIsTrue); - } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { + } else if (newX.stamp(NodeView.DEFAULT) instanceof IntegerStamp && newY.stamp(NodeView.DEFAULT) instanceof IntegerStamp) { return new IntegerLessThanNode(newX, newY); } throw GraalError.shouldNotReachHere(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java index 4d870566e73..03e963d18d4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.code.CodeUtil; @@ -45,25 +46,27 @@ public final class IntegerBelowNode extends IntegerLowerThanNode { public IntegerBelowNode(ValueNode x, ValueNode y) { super(TYPE, x, y, OP); - assert x.stamp() instanceof IntegerStamp; - assert y.stamp() instanceof IntegerStamp; + assert x.stamp(NodeView.DEFAULT) instanceof IntegerStamp; + assert y.stamp(NodeView.DEFAULT) instanceof IntegerStamp; } - public static LogicNode create(ValueNode x, ValueNode y) { - return OP.create(x, y); + public static LogicNode create(ValueNode x, ValueNode y, NodeView view) { + return OP.create(x, y, view); } - public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y) { - LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, OP.getCondition(), false, x, y); + public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y, + NodeView view) { + LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, OP.getCondition(), false, x, y, view); if (value != null) { return value; } - return create(x, y); + return create(x, y, view); } @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), OP.getCondition(), false, forX, forY); + NodeView view = NodeView.from(tool); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), OP.getCondition(), false, forX, forY, view); if (value != null) { return value; } @@ -72,8 +75,8 @@ public final class IntegerBelowNode extends IntegerLowerThanNode { public static class BelowOp extends LowerOp { @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue) { - assert newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp; + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) { + assert newX.stamp(NodeView.DEFAULT) instanceof IntegerStamp && newY.stamp(NodeView.DEFAULT) instanceof IntegerStamp; return new IntegerBelowNode(newX, newY); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java index 90bfdfde901..0e601f2910e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ArithmeticOperation; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -61,12 +62,12 @@ public abstract class IntegerConvertNode extends UnaryNode implements A protected IntegerConvertNode(NodeClass> c, SerializableIntegerConvertFunction getOp, SerializableIntegerConvertFunction getReverseOp, int inputBits, int resultBits, ValueNode input) { - super(c, getOp.apply(ArithmeticOpTable.forStamp(input.stamp())).foldStamp(inputBits, resultBits, input.stamp()), input); + super(c, getOp.apply(ArithmeticOpTable.forStamp(input.stamp(NodeView.DEFAULT))).foldStamp(inputBits, resultBits, input.stamp(NodeView.DEFAULT)), input); this.getOp = getOp; this.getReverseOp = getReverseOp; this.inputBits = inputBits; this.resultBits = resultBits; - assert ((PrimitiveStamp) input.stamp()).getBits() == inputBits; + assert ((PrimitiveStamp) input.stamp(NodeView.DEFAULT)).getBits() == inputBits; } public int getInputBits() { @@ -78,7 +79,7 @@ public abstract class IntegerConvertNode extends UnaryNode implements A } protected final IntegerConvertOp getOp(ValueNode forValue) { - return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp())); + return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT))); } @Override @@ -93,19 +94,19 @@ public abstract class IntegerConvertNode extends UnaryNode implements A @Override public Constant reverse(Constant c, ConstantReflectionProvider constantReflection) { - IntegerConvertOp reverse = getReverseOp.apply(ArithmeticOpTable.forStamp(stamp())); + IntegerConvertOp reverse = getReverseOp.apply(ArithmeticOpTable.forStamp(stamp(NodeView.DEFAULT))); return reverse.foldConstant(getResultBits(), getInputBits(), c); } @Override public Stamp foldStamp(Stamp newStamp) { - assert newStamp.isCompatible(getValue().stamp()); + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); return getArithmeticOp().foldStamp(inputBits, resultBits, newStamp); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - ValueNode synonym = findSynonym(getOp(forValue), forValue, inputBits, resultBits, stamp()); + ValueNode synonym = findSynonym(getOp(forValue), forValue, inputBits, resultBits, stamp(NodeView.DEFAULT)); if (synonym != null) { return synonym; } @@ -121,12 +122,12 @@ public abstract class IntegerConvertNode extends UnaryNode implements A return null; } - public static ValueNode convert(ValueNode input, Stamp stamp) { - return convert(input, stamp, false); + public static ValueNode convert(ValueNode input, Stamp stamp, NodeView view) { + return convert(input, stamp, false, view); } - public static ValueNode convert(ValueNode input, Stamp stamp, StructuredGraph graph) { - ValueNode convert = convert(input, stamp, false); + public static ValueNode convert(ValueNode input, Stamp stamp, StructuredGraph graph, NodeView view) { + ValueNode convert = convert(input, stamp, false, view); if (!convert.isAlive()) { assert !convert.isDeleted(); convert = graph.addOrUniqueWithInputs(convert); @@ -134,12 +135,12 @@ public abstract class IntegerConvertNode extends UnaryNode implements A return convert; } - public static ValueNode convertUnsigned(ValueNode input, Stamp stamp) { - return convert(input, stamp, true); + public static ValueNode convertUnsigned(ValueNode input, Stamp stamp, NodeView view) { + return convert(input, stamp, true, view); } - public static ValueNode convert(ValueNode input, Stamp stamp, boolean zeroExtend) { - IntegerStamp fromStamp = (IntegerStamp) input.stamp(); + public static ValueNode convert(ValueNode input, Stamp stamp, boolean zeroExtend, NodeView view) { + IntegerStamp fromStamp = (IntegerStamp) input.stamp(view); IntegerStamp toStamp = (IntegerStamp) stamp; ValueNode result; @@ -149,13 +150,13 @@ public abstract class IntegerConvertNode extends UnaryNode implements A result = new NarrowNode(input, fromStamp.getBits(), toStamp.getBits()); } else if (zeroExtend) { // toStamp.getBits() > fromStamp.getBits() - result = ZeroExtendNode.create(input, toStamp.getBits()); + result = ZeroExtendNode.create(input, toStamp.getBits(), view); } else { // toStamp.getBits() > fromStamp.getBits() - result = SignExtendNode.create(input, toStamp.getBits()); + result = SignExtendNode.create(input, toStamp.getBits(), view); } - IntegerStamp resultStamp = (IntegerStamp) result.stamp(); + IntegerStamp resultStamp = (IntegerStamp) result.stamp(view); assert toStamp.getBits() == resultStamp.getBits(); return result; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java index 97766cabec8..7a25afd4025 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -59,7 +60,7 @@ public abstract class IntegerDivRemNode extends FixedBinaryNode implements Lower // Assigning canDeopt during constructor, because it must never change during lifetime of // the node. - this.canDeopt = ((IntegerStamp) getY().stamp()).contains(0); + this.canDeopt = ((IntegerStamp) getY().stamp(NodeView.DEFAULT)).contains(0); } public final Op getOp() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java index dbb929d9ff9..8408d73e315 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -59,8 +60,8 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object; } - public static LogicNode create(ValueNode x, ValueNode y) { - LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false); + public static LogicNode create(ValueNode x, ValueNode y, NodeView view) { + LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false, view); if (result != null) { return result; } @@ -84,17 +85,19 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut return new IntegerEqualsNode(x, y).maybeCommuteInputs(); } - public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y) { - LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y); + public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y, + NodeView view) { + LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y, view); if (value != null) { return value; } - return create(x, y); + return create(x, y, view); } @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY); + NodeView view = NodeView.from(tool); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view); if (value != null) { return value; } @@ -104,7 +107,7 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut public static class IntegerEqualsOp extends CompareOp { @Override protected LogicNode optimizeNormalizeCompare(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { + Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored, NodeView view) { PrimitiveConstant primitive = (PrimitiveConstant) constant; ValueNode a = normalizeNode.getX(); ValueNode b = normalizeNode.getY(); @@ -112,21 +115,21 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut if (cst == 0) { if (normalizeNode.getX().getStackKind() == JavaKind.Double || normalizeNode.getX().getStackKind() == JavaKind.Float) { - return FloatEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b); + return FloatEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b, view); } else { - return IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b); + return IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b, view); } } else if (cst == 1) { if (normalizeNode.getX().getStackKind() == JavaKind.Double || normalizeNode.getX().getStackKind() == JavaKind.Float) { - return FloatLessThanNode.create(b, a, !normalizeNode.isUnorderedLess); + return FloatLessThanNode.create(b, a, !normalizeNode.isUnorderedLess, view); } else { - return IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, b, a); + return IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, b, a, view); } } else if (cst == -1) { if (normalizeNode.getX().getStackKind() == JavaKind.Double || normalizeNode.getX().getStackKind() == JavaKind.Float) { - return FloatLessThanNode.create(a, b, normalizeNode.isUnorderedLess); + return FloatLessThanNode.create(a, b, normalizeNode.isUnorderedLess, view); } else { - return IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b); + return IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b, view); } } else { return LogicConstantNode.contradiction(); @@ -134,12 +137,12 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut } @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue) { - if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) { + if (newX.stamp(view) instanceof FloatStamp && newY.stamp(view) instanceof FloatStamp) { return new FloatEqualsNode(newX, newY); - } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { + } else if (newX.stamp(view) instanceof IntegerStamp && newY.stamp(view) instanceof IntegerStamp) { return new IntegerEqualsNode(newX, newY); - } else if (newX.stamp() instanceof AbstractPointerStamp && newY.stamp() instanceof AbstractPointerStamp) { + } else if (newX.stamp(view) instanceof AbstractPointerStamp && newY.stamp(view) instanceof AbstractPointerStamp) { return new IntegerEqualsNode(newX, newY); } throw GraalError.shouldNotReachHere(); @@ -147,10 +150,10 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut @Override public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, - boolean unorderedIsTrue, ValueNode forX, ValueNode forY) { + boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return LogicConstantNode.tautology(); - } else if (forX.stamp().alwaysDistinct(forY.stamp())) { + } else if (forX.stamp(view).alwaysDistinct(forY.stamp(view))) { return LogicConstantNode.contradiction(); } @@ -174,19 +177,19 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut } if (v1 != null) { assert v2 != null; - return create(v1, v2); + return create(v1, v2, view); } } - return super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY); + return super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); } @Override protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue) { + Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { if (constant instanceof PrimitiveConstant) { PrimitiveConstant primitiveConstant = (PrimitiveConstant) constant; - IntegerStamp nonConstantStamp = ((IntegerStamp) nonConstant.stamp()); + IntegerStamp nonConstantStamp = ((IntegerStamp) nonConstant.stamp(view)); if ((primitiveConstant.asLong() == 1 && nonConstantStamp.upperBound() == 1 && nonConstantStamp.lowerBound() == 0) || (primitiveConstant.asLong() == -1 && nonConstantStamp.upperBound() == 0 && nonConstantStamp.lowerBound() == -1)) { // nonConstant can only be 0 or 1 (respective -1), test against 0 instead of 1 @@ -194,15 +197,16 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut // execution // on specific platforms. return LogicNegationNode.create( - IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, nonConstant, ConstantNode.forIntegerKind(nonConstant.getStackKind(), 0))); + IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, nonConstant, ConstantNode.forIntegerKind(nonConstant.getStackKind(), 0), + view)); } else if (primitiveConstant.asLong() == 0) { if (nonConstant instanceof AndNode) { AndNode andNode = (AndNode) nonConstant; return new IntegerTestNode(andNode.getX(), andNode.getY()); } else if (nonConstant instanceof SubNode) { SubNode subNode = (SubNode) nonConstant; - return IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, subNode.getX(), subNode.getY()); - } else if (nonConstant instanceof ShiftNode && nonConstant.stamp() instanceof IntegerStamp) { + return IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, subNode.getX(), subNode.getY(), view); + } else if (nonConstant instanceof ShiftNode && nonConstant.stamp(view) instanceof IntegerStamp) { if (nonConstant instanceof LeftShiftNode) { LeftShiftNode shift = (LeftShiftNode) nonConstant; if (shift.getY().isConstant()) { @@ -217,7 +221,7 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut } } else if (nonConstant instanceof RightShiftNode) { RightShiftNode shift = (RightShiftNode) nonConstant; - if (shift.getY().isConstant() && ((IntegerStamp) shift.getX().stamp()).isPositive()) { + if (shift.getY().isConstant() && ((IntegerStamp) shift.getX().stamp(view)).isPositive()) { int mask = shift.getShiftAmountMask(); int amount = shift.getY().asJavaConstant().asInt() & mask; if (shift.getX().getStackKind() == JavaKind.Int) { @@ -258,16 +262,16 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut } } - if (nonConstant instanceof XorNode && nonConstant.stamp() instanceof IntegerStamp) { + if (nonConstant instanceof XorNode && nonConstant.stamp(view) instanceof IntegerStamp) { XorNode xorNode = (XorNode) nonConstant; - if (xorNode.getY().isJavaConstant() && xorNode.getY().asJavaConstant().asLong() == 1 && ((IntegerStamp) xorNode.getX().stamp()).upMask() == 1) { + if (xorNode.getY().isJavaConstant() && xorNode.getY().asJavaConstant().asLong() == 1 && ((IntegerStamp) xorNode.getX().stamp(view)).upMask() == 1) { // x ^ 1 == 0 is the same as x == 1 if x in [0, 1] // x ^ 1 == 1 is the same as x == 0 if x in [0, 1] - return new IntegerEqualsNode(xorNode.getX(), ConstantNode.forIntegerStamp(xorNode.getX().stamp(), primitiveConstant.asLong() ^ 1)); + return new IntegerEqualsNode(xorNode.getX(), ConstantNode.forIntegerStamp(xorNode.getX().stamp(view), primitiveConstant.asLong() ^ 1)); } } } - return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue); + return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue, view); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java index bce2a2c39f3..bab63e1f7d9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.code.CodeUtil; @@ -60,22 +61,23 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object; } - public static LogicNode create(ValueNode x, ValueNode y) { - return OP.create(x, y); + public static LogicNode create(ValueNode x, ValueNode y, NodeView view) { + return OP.create(x, y, view); } public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - ValueNode x, ValueNode y) { - LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, OP.getCondition(), false, x, y); + ValueNode x, ValueNode y, NodeView view) { + LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, OP.getCondition(), false, x, y, view); if (value != null) { return value; } - return create(x, y); + return create(x, y, view); } @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), OP.getCondition(), false, forX, forY); + NodeView view = NodeView.from(tool); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), OP.getCondition(), false, forX, forY, view); if (value != null) { return value; } @@ -98,11 +100,11 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { public static class LessThanOp extends LowerOp { @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue) { - if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) { + if (newX.stamp(view) instanceof FloatStamp && newY.stamp(view) instanceof FloatStamp) { return new FloatLessThanNode(newX, newY, unorderedIsTrue); // TODO: Is the last arg // supposed to be true? - } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { + } else if (newX.stamp(view) instanceof IntegerStamp && newY.stamp(view) instanceof IntegerStamp) { return new IntegerLessThanNode(newX, newY); } throw GraalError.shouldNotReachHere(); @@ -110,7 +112,7 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { @Override protected LogicNode optimizeNormalizeCompare(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { + Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored, NodeView view) { PrimitiveConstant primitive = (PrimitiveConstant) constant; /* @formatter:off * a NC b < c (not mirrored) @@ -138,18 +140,18 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { if (cst == 0) { if (normalizeNode.getX().getStackKind() == JavaKind.Double || normalizeNode.getX().getStackKind() == JavaKind.Float) { - return FloatLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b, mirrored ^ normalizeNode.isUnorderedLess); + return FloatLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b, mirrored ^ normalizeNode.isUnorderedLess, view); } else { - return IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b); + return IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, a, b, view); } } else if (cst == 1) { // a <= b <=> !(a > b) LogicNode compare; if (normalizeNode.getX().getStackKind() == JavaKind.Double || normalizeNode.getX().getStackKind() == JavaKind.Float) { // since we negate, we have to reverse the unordered result - compare = FloatLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, b, a, mirrored == normalizeNode.isUnorderedLess); + compare = FloatLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, b, a, mirrored == normalizeNode.isUnorderedLess, view); } else { - compare = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, b, a); + compare = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, b, a, view); } return LogicNegationNode.create(compare); } else if (cst <= -1) { @@ -161,13 +163,13 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { } @Override - protected LogicNode findSynonym(ValueNode forX, ValueNode forY) { - LogicNode result = super.findSynonym(forX, forY); + protected LogicNode findSynonym(ValueNode forX, ValueNode forY, NodeView view) { + LogicNode result = super.findSynonym(forX, forY, view); if (result != null) { return result; } - if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { - if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) { + if (forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) { + if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(view), (IntegerStamp) forY.stamp(view))) { return new IntegerBelowNode(forX, forY); } } @@ -188,8 +190,8 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { } if (xx != null) { assert yy != null; - IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp(); - IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp(); + IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp(view); + IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp(view); long minValue = CodeUtil.minValue(xStamp.getBits()); long maxValue = CodeUtil.maxValue(xStamp.getBits()); @@ -203,10 +205,10 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { } } - if (forX.stamp() instanceof IntegerStamp) { - assert forY.stamp() instanceof IntegerStamp; - int bits = ((IntegerStamp) forX.stamp()).getBits(); - assert ((IntegerStamp) forY.stamp()).getBits() == bits; + if (forX.stamp(view) instanceof IntegerStamp) { + assert forY.stamp(view) instanceof IntegerStamp; + int bits = ((IntegerStamp) forX.stamp(view)).getBits(); + assert ((IntegerStamp) forY.stamp(view)).getBits() == bits; long min = OP.minValue(bits); long xResidue = 0; ValueNode left = null; @@ -240,12 +242,12 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { if (left == null) { left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min); } else if (xResidue != 0) { - left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue)); + left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue), view); } if (right == null) { right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min); } else if (yResidue != 0) { - right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue)); + right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue), view); } return new IntegerBelowNode(left, right); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java index 9ec1d8fe20d..0294ef39a7f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -76,12 +77,12 @@ public abstract class IntegerLowerThanNode extends CompareNode { IntegerStamp xStamp = (IntegerStamp) xStampGeneric; AddNode addNode = (AddNode) forY; IntegerStamp aStamp = null; - if (addNode.getX() == forX && addNode.getY().stamp() instanceof IntegerStamp) { + if (addNode.getX() == forX && addNode.getY().stamp(NodeView.DEFAULT) instanceof IntegerStamp) { // x < x + a - aStamp = (IntegerStamp) addNode.getY().stamp(); - } else if (addNode.getY() == forX && addNode.getX().stamp() instanceof IntegerStamp) { + aStamp = (IntegerStamp) addNode.getY().stamp(NodeView.DEFAULT); + } else if (addNode.getY() == forX && addNode.getX().stamp(NodeView.DEFAULT) instanceof IntegerStamp) { // x < a + x - aStamp = (IntegerStamp) addNode.getX().stamp(); + aStamp = (IntegerStamp) addNode.getX().stamp(NodeView.DEFAULT); } if (aStamp != null) { IntegerStamp result = getOp().getSucceedingStampForXLowerXPlusA(mirror, strict, aStamp); @@ -117,12 +118,12 @@ public abstract class IntegerLowerThanNode extends CompareNode { public abstract static class LowerOp extends CompareOp { @Override public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, - boolean unorderedIsTrue, ValueNode forX, ValueNode forY) { - LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY); + boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { + LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); if (result != null) { return result; } - LogicNode synonym = findSynonym(forX, forY); + LogicNode synonym = findSynonym(forX, forY, view); if (synonym != null) { return synonym; } @@ -159,12 +160,12 @@ public abstract class IntegerLowerThanNode extends CompareNode { protected abstract IntegerLowerThanNode createNode(ValueNode x, ValueNode y); - public LogicNode create(ValueNode x, ValueNode y) { - LogicNode result = CompareNode.tryConstantFoldPrimitive(getCondition(), x, y, false); + public LogicNode create(ValueNode x, ValueNode y, NodeView view) { + LogicNode result = CompareNode.tryConstantFoldPrimitive(getCondition(), x, y, false, view); if (result != null) { return result; } else { - result = findSynonym(x, y); + result = findSynonym(x, y, view); if (result != null) { return result; } @@ -172,47 +173,47 @@ public abstract class IntegerLowerThanNode extends CompareNode { } } - protected LogicNode findSynonym(ValueNode forX, ValueNode forY) { + protected LogicNode findSynonym(ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return LogicConstantNode.contradiction(); } - TriState fold = tryFold(forX.stamp(), forY.stamp()); + TriState fold = tryFold(forX.stamp(view), forY.stamp(view)); if (fold.isTrue()) { return LogicConstantNode.tautology(); } else if (fold.isFalse()) { return LogicConstantNode.contradiction(); } - if (forY.stamp() instanceof IntegerStamp) { - IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + if (forY.stamp(view) instanceof IntegerStamp) { + IntegerStamp yStamp = (IntegerStamp) forY.stamp(view); int bits = yStamp.getBits(); if (forX.isJavaConstant() && !forY.isConstant()) { // bring the constant on the right long xValue = forX.asJavaConstant().asLong(); if (xValue != maxValue(bits)) { // c < x <=> !(c >= x) <=> !(x <= c) <=> !(x < c + 1) - return LogicNegationNode.create(create(forY, ConstantNode.forIntegerStamp(yStamp, xValue + 1))); + return LogicNegationNode.create(create(forY, ConstantNode.forIntegerStamp(yStamp, xValue + 1), view)); } } if (forY.isJavaConstant()) { long yValue = forY.asJavaConstant().asLong(); if (yValue == maxValue(bits)) { // x < MAX <=> x != MAX - return LogicNegationNode.create(IntegerEqualsNode.create(forX, forY)); + return LogicNegationNode.create(IntegerEqualsNode.create(forX, forY, view)); } if (yValue == minValue(bits) + 1) { // x < MIN + 1 <=> x <= MIN <=> x == MIN - return IntegerEqualsNode.create(forX, ConstantNode.forIntegerStamp(yStamp, minValue(bits))); + return IntegerEqualsNode.create(forX, ConstantNode.forIntegerStamp(yStamp, minValue(bits)), view); } } else if (forY instanceof AddNode) { AddNode addNode = (AddNode) forY; - LogicNode canonical = canonicalizeXLowerXPlusA(forX, addNode, false, true); + LogicNode canonical = canonicalizeXLowerXPlusA(forX, addNode, false, true, view); if (canonical != null) { return canonical; } } if (forX instanceof AddNode) { AddNode addNode = (AddNode) forX; - LogicNode canonical = canonicalizeXLowerXPlusA(forY, addNode, true, false); + LogicNode canonical = canonicalizeXLowerXPlusA(forY, addNode, true, false, view); if (canonical != null) { return canonical; } @@ -221,32 +222,32 @@ public abstract class IntegerLowerThanNode extends CompareNode { return null; } - private LogicNode canonicalizeXLowerXPlusA(ValueNode forX, AddNode addNode, boolean mirrored, boolean strict) { + private LogicNode canonicalizeXLowerXPlusA(ValueNode forX, AddNode addNode, boolean mirrored, boolean strict, NodeView view) { // x < x + a IntegerStamp succeedingXStamp; boolean exact; - if (addNode.getX() == forX && addNode.getY().stamp() instanceof IntegerStamp) { - IntegerStamp aStamp = (IntegerStamp) addNode.getY().stamp(); + if (addNode.getX() == forX && addNode.getY().stamp(view) instanceof IntegerStamp) { + IntegerStamp aStamp = (IntegerStamp) addNode.getY().stamp(view); succeedingXStamp = getSucceedingStampForXLowerXPlusA(mirrored, strict, aStamp); exact = aStamp.lowerBound() == aStamp.upperBound(); - } else if (addNode.getY() == forX && addNode.getX().stamp() instanceof IntegerStamp) { - IntegerStamp aStamp = (IntegerStamp) addNode.getX().stamp(); + } else if (addNode.getY() == forX && addNode.getX().stamp(view) instanceof IntegerStamp) { + IntegerStamp aStamp = (IntegerStamp) addNode.getX().stamp(view); succeedingXStamp = getSucceedingStampForXLowerXPlusA(mirrored, strict, aStamp); exact = aStamp.lowerBound() == aStamp.upperBound(); } else { return null; } - if (succeedingXStamp.join(forX.stamp()).isEmpty()) { + if (succeedingXStamp.join(forX.stamp(view)).isEmpty()) { return LogicConstantNode.contradiction(); } else if (exact && !succeedingXStamp.isEmpty()) { int bits = succeedingXStamp.getBits(); if (compare(lowerBound(succeedingXStamp), minValue(bits)) > 0) { assert upperBound(succeedingXStamp) == maxValue(bits); // x must be in [L..MAX] <=> x >= L <=> !(x < L) - return LogicNegationNode.create(create(forX, ConstantNode.forIntegerStamp(succeedingXStamp, lowerBound(succeedingXStamp)))); + return LogicNegationNode.create(create(forX, ConstantNode.forIntegerStamp(succeedingXStamp, lowerBound(succeedingXStamp)), view)); } else if (compare(upperBound(succeedingXStamp), maxValue(bits)) < 0) { // x must be in [MIN..H] <=> x <= H <=> !(H < x) - return LogicNegationNode.create(create(ConstantNode.forIntegerStamp(succeedingXStamp, upperBound(succeedingXStamp)), forX)); + return LogicNegationNode.create(create(ConstantNode.forIntegerStamp(succeedingXStamp, upperBound(succeedingXStamp)), forX, view)); } } return null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java index cf7feb6971e..0e837972d75 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.BinaryOpLogicNode; import org.graalvm.compiler.nodes.LogicConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.meta.TriState; @@ -52,12 +53,13 @@ public final class IntegerTestNode extends BinaryOpLogicNode implements BinaryCo @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); if (forX.isConstant() && forY.isConstant()) { return LogicConstantNode.forBoolean((forX.asJavaConstant().asLong() & forY.asJavaConstant().asLong()) == 0); } - if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { - IntegerStamp xStamp = (IntegerStamp) forX.stamp(); - IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + if (forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) forX.stamp(view); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(view); if ((xStamp.upMask() & yStamp.upMask()) == 0) { return LogicConstantNode.tautology(); } else if ((xStamp.downMask() & yStamp.downMask()) != 0) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java index 68b5700559b..85de8712869 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.UnaryOpLogicNode; import org.graalvm.compiler.nodes.ValueNode; @@ -77,7 +78,7 @@ public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, @Override public boolean verify() { assertTrue(getValue() != null, "is null input must not be null"); - assertTrue(getValue().stamp() instanceof AbstractPointerStamp, "input must be a pointer not %s", getValue().stamp()); + assertTrue(getValue().stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp, "input must be a pointer not %s", getValue().stamp(NodeView.DEFAULT)); return super.verify(); } @@ -113,7 +114,7 @@ public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, @Override public void virtualize(VirtualizerTool tool) { ValueNode alias = tool.getAlias(getValue()); - TriState fold = tryFold(alias.stamp()); + TriState fold = tryFold(alias.stamp(NodeView.DEFAULT)); if (fold != TriState.UNKNOWN) { tool.replaceWithValue(LogicConstantNode.forBoolean(fold.isTrue(), graph())); } @@ -122,7 +123,7 @@ public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, @Override public Stamp getSucceedingStampForValue(boolean negated) { // Ignore any more precise input stamp since canonicalization will skip through PiNodes - AbstractPointerStamp pointerStamp = (AbstractPointerStamp) getValue().stamp().unrestricted(); + AbstractPointerStamp pointerStamp = (AbstractPointerStamp) getValue().stamp(NodeView.DEFAULT).unrestricted(); return negated ? pointerStamp.asNonNull() : pointerStamp.asAlwaysNull(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/LeftShiftNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/LeftShiftNode.java index f9d7cf3ed6e..98186ee15c3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/LeftShiftNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/LeftShiftNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -45,10 +46,10 @@ public final class LeftShiftNode extends ShiftNode { super(TYPE, ArithmeticOpTable::getShl, x, y); } - public static ValueNode create(ValueNode x, ValueNode y) { - ArithmeticOpTable.ShiftOp op = ArithmeticOpTable.forStamp(x.stamp()).getShl(); - Stamp stamp = op.foldStamp(x.stamp(), (IntegerStamp) y.stamp()); - ValueNode value = ShiftNode.canonical(op, stamp, x, y); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + ArithmeticOpTable.ShiftOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getShl(); + Stamp stamp = op.foldStamp(x.stamp(view), (IntegerStamp) y.stamp(view)); + ValueNode value = ShiftNode.canonical(op, stamp, x, y, view); if (value != null) { return value; } @@ -63,7 +64,7 @@ public final class LeftShiftNode extends ShiftNode { return ret; } - return canonical(this, getArithmeticOp(), stamp(), forX, forY); + return canonical(this, getArithmeticOp(), stamp(NodeView.DEFAULT), forX, forY); } private static ValueNode canonical(LeftShiftNode leftShiftNode, ArithmeticOpTable.ShiftOp op, Stamp stamp, ValueNode forX, ValueNode forY) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java index 8f1c8879172..6f5cec5c454 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -56,14 +57,14 @@ public class MulNode extends BinaryArithmeticNode implements NarrowableArit super(c, ArithmeticOpTable::getMul, x, y); } - public static ValueNode create(ValueNode x, ValueNode y) { - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getMul(); - Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); - ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getMul(); + Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); if (tryConstantFold != null) { return tryConstantFold; } - return canonical(null, op, stamp, x, y); + return canonical(null, op, stamp, x, y, view); } @Override @@ -83,10 +84,11 @@ public class MulNode extends BinaryArithmeticNode implements NarrowableArit return new MulNode(forY, forX); } BinaryOp op = getOp(forX, forY); - return canonical(this, op, stamp(), forX, forY); + NodeView view = NodeView.from(tool); + return canonical(this, op, stamp(view), forX, forY, view); } - private static ValueNode canonical(MulNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY) { + private static ValueNode canonical(MulNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { if (forY.isConstant()) { Constant c = forY.asConstant(); if (op.isNeutral(c)) { @@ -95,57 +97,64 @@ public class MulNode extends BinaryArithmeticNode implements NarrowableArit if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { long i = ((PrimitiveConstant) c).asLong(); - - if (i == 0) { - return ConstantNode.forIntegerStamp(stamp, 0); - } else if (i == 1) { - return forX; - } else if (i == -1) { - return NegateNode.create(forX); - } else if (i > 0) { - if (CodeUtil.isPowerOf2(i)) { - return new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i))); - } else if (CodeUtil.isPowerOf2(i - 1)) { - return AddNode.create(new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i - 1))), forX); - } else if (CodeUtil.isPowerOf2(i + 1)) { - return SubNode.create(new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i + 1))), forX); - } else { - int bitCount = Long.bitCount(i); - long highestBitValue = Long.highestOneBit(i); - if (bitCount == 2) { - // e.g., 0b1000_0010 - long lowerBitValue = i - highestBitValue; - assert highestBitValue > 0 && lowerBitValue > 0; - ValueNode left = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(highestBitValue))); - ValueNode right = lowerBitValue == 1 ? forX : new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(lowerBitValue))); - return AddNode.create(left, right); - } else { - // e.g., 0b1111_1101 - int shiftToRoundUpToPowerOf2 = CodeUtil.log2(highestBitValue) + 1; - long subValue = (1 << shiftToRoundUpToPowerOf2) - i; - if (CodeUtil.isPowerOf2(subValue) && shiftToRoundUpToPowerOf2 < ((IntegerStamp) stamp).getBits()) { - assert CodeUtil.log2(subValue) >= 1; - ValueNode left = new LeftShiftNode(forX, ConstantNode.forInt(shiftToRoundUpToPowerOf2)); - ValueNode right = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(subValue))); - return SubNode.create(left, right); - } - } - } - } else if (i < 0) { - if (CodeUtil.isPowerOf2(-i)) { - return NegateNode.create(LeftShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(-i)))); - } + ValueNode result = canonical(stamp, forX, i, view); + if (result != null) { + return result; } } if (op.isAssociative()) { // canonicalize expressions like "(a * 1) * 2" - return reassociate(self != null ? self : (MulNode) new MulNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY); + return reassociate(self != null ? self : (MulNode) new MulNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); } } return self != null ? self : new MulNode(forX, forY).maybeCommuteInputs(); } + public static ValueNode canonical(Stamp stamp, ValueNode forX, long i, NodeView view) { + if (i == 0) { + return ConstantNode.forIntegerStamp(stamp, 0); + } else if (i == 1) { + return forX; + } else if (i == -1) { + return NegateNode.create(forX, view); + } else if (i > 0) { + if (CodeUtil.isPowerOf2(i)) { + return new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i))); + } else if (CodeUtil.isPowerOf2(i - 1)) { + return AddNode.create(new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i - 1))), forX, view); + } else if (CodeUtil.isPowerOf2(i + 1)) { + return SubNode.create(new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i + 1))), forX, view); + } else { + int bitCount = Long.bitCount(i); + long highestBitValue = Long.highestOneBit(i); + if (bitCount == 2) { + // e.g., 0b1000_0010 + long lowerBitValue = i - highestBitValue; + assert highestBitValue > 0 && lowerBitValue > 0; + ValueNode left = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(highestBitValue))); + ValueNode right = lowerBitValue == 1 ? forX : new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(lowerBitValue))); + return AddNode.create(left, right, view); + } else { + // e.g., 0b1111_1101 + int shiftToRoundUpToPowerOf2 = CodeUtil.log2(highestBitValue) + 1; + long subValue = (1 << shiftToRoundUpToPowerOf2) - i; + if (CodeUtil.isPowerOf2(subValue) && shiftToRoundUpToPowerOf2 < ((IntegerStamp) stamp).getBits()) { + assert CodeUtil.log2(subValue) >= 1; + ValueNode left = new LeftShiftNode(forX, ConstantNode.forInt(shiftToRoundUpToPowerOf2)); + ValueNode right = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(subValue))); + return SubNode.create(left, right, view); + } + } + } + } else if (i < 0) { + if (CodeUtil.isPowerOf2(-i)) { + return NegateNode.create(LeftShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(-i)), view), view); + } + } + return null; + } + @Override public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) { Value op1 = nodeValueMap.operand(getX()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java index 766c6f854a9..e417e65cb88 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -48,21 +49,21 @@ public final class NarrowNode extends IntegerConvertNode { public static final NodeClass TYPE = NodeClass.create(NarrowNode.class); public NarrowNode(ValueNode input, int resultBits) { - this(input, PrimitiveStamp.getBits(input.stamp()), resultBits); - assert 0 < resultBits && resultBits <= PrimitiveStamp.getBits(input.stamp()); + this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits); + assert 0 < resultBits && resultBits <= PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)); } public NarrowNode(ValueNode input, int inputBits, int resultBits) { super(TYPE, ArithmeticOpTable::getNarrow, ArithmeticOpTable::getSignExtend, inputBits, resultBits, input); } - public static ValueNode create(ValueNode input, int resultBits) { - return create(input, PrimitiveStamp.getBits(input.stamp()), resultBits); + public static ValueNode create(ValueNode input, int resultBits, NodeView view) { + return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view); } - public static ValueNode create(ValueNode input, int inputBits, int resultBits) { - IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp()).getNarrow(); - ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp())); + public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) { + IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getNarrow(); + ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view))); if (synonym != null) { return synonym; } else { @@ -77,6 +78,7 @@ public final class NarrowNode extends IntegerConvertNode { @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + NodeView view = NodeView.from(tool); ValueNode ret = super.canonical(tool, forValue); if (ret != this) { return ret; @@ -108,7 +110,7 @@ public final class NarrowNode extends IntegerConvertNode { if (other instanceof SignExtendNode) { // sxxx -(sign-extend)-> ssssssss sssssxxx -(narrow)-> sssssxxx // ==> sxxx -(sign-extend)-> sssssxxx - return SignExtendNode.create(other.getValue(), other.getInputBits(), getResultBits()); + return SignExtendNode.create(other.getValue(), other.getInputBits(), getResultBits(), view); } else if (other instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx // ==> xxxx -(zero-extend)-> 0000xxxx @@ -117,13 +119,13 @@ public final class NarrowNode extends IntegerConvertNode { } } else if (forValue instanceof AndNode) { AndNode andNode = (AndNode) forValue; - IntegerStamp yStamp = (IntegerStamp) andNode.getY().stamp(); - IntegerStamp xStamp = (IntegerStamp) andNode.getX().stamp(); + IntegerStamp yStamp = (IntegerStamp) andNode.getY().stamp(view); + IntegerStamp xStamp = (IntegerStamp) andNode.getX().stamp(view); long relevantMask = CodeUtil.mask(this.getResultBits()); if ((relevantMask & yStamp.downMask()) == relevantMask) { - return create(andNode.getX(), this.getResultBits()); + return create(andNode.getX(), this.getResultBits(), view); } else if ((relevantMask & xStamp.downMask()) == relevantMask) { - return create(andNode.getY(), this.getResultBits()); + return create(andNode.getY(), this.getResultBits(), view); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NegateNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NegateNode.java index ff563c7a94d..0ee81cc2bf8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NegateNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NegateNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.StampInverter; @@ -49,8 +50,8 @@ public final class NegateNode extends UnaryArithmeticNode implements Narrow super(TYPE, ArithmeticOpTable::getNeg, value); } - public static ValueNode create(ValueNode value) { - ValueNode synonym = findSynonym(value); + public static ValueNode create(ValueNode value, NodeView view) { + ValueNode synonym = findSynonym(value, view); if (synonym != null) { return synonym; } @@ -66,8 +67,8 @@ public final class NegateNode extends UnaryArithmeticNode implements Narrow return this; } - protected static ValueNode findSynonym(ValueNode forValue) { - ArithmeticOpTable.UnaryOp negOp = ArithmeticOpTable.forStamp(forValue.stamp()).getNeg(); + protected static ValueNode findSynonym(ValueNode forValue, NodeView view) { + ArithmeticOpTable.UnaryOp negOp = ArithmeticOpTable.forStamp(forValue.stamp(view)).getNeg(); ValueNode synonym = UnaryArithmeticNode.findSynonym(forValue, negOp); if (synonym != null) { return synonym; @@ -75,9 +76,9 @@ public final class NegateNode extends UnaryArithmeticNode implements Narrow if (forValue instanceof NegateNode) { return ((NegateNode) forValue).getValue(); } - if (forValue instanceof SubNode && !(forValue.stamp() instanceof FloatStamp)) { + if (forValue instanceof SubNode && !(forValue.stamp(view) instanceof FloatStamp)) { SubNode sub = (SubNode) forValue; - return SubNode.create(sub.getY(), sub.getX()); + return SubNode.create(sub.getY(), sub.getX(), view); } return null; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java index 049ff137986..6faad2746c4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -86,7 +87,8 @@ public final class NormalizeCompareNode extends BinaryNode implements IterableNo @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode result = tryConstantFold(x, y, isUnorderedLess, stamp().getStackKind(), tool.getConstantReflection()); + NodeView view = NodeView.from(tool); + ValueNode result = tryConstantFold(x, y, isUnorderedLess, stamp(view).getStackKind(), tool.getConstantReflection()); if (result != null) { return result; } @@ -100,7 +102,7 @@ public final class NormalizeCompareNode extends BinaryNode implements IterableNo @Override public Stamp foldStamp(Stamp stampX, Stamp stampY) { - return stamp(); + return stamp(NodeView.DEFAULT); } public boolean isUnorderedLess() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NotNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NotNode.java index 0fbfd223295..3e79b87c572 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NotNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NotNode.java @@ -45,20 +45,31 @@ public final class NotNode extends UnaryArithmeticNode implements Arithmeti public static final NodeClass TYPE = NodeClass.create(NotNode.class); - public NotNode(ValueNode x) { + protected NotNode(ValueNode x) { super(TYPE, ArithmeticOpTable::getNot, x); } + public static ValueNode create(ValueNode x) { + return canonicalize(null, x); + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { ValueNode ret = super.canonical(tool, forValue); if (ret != this) { return ret; } - if (forValue instanceof NotNode) { - return ((NotNode) forValue).getValue(); + return canonicalize(this, forValue); + } + + private static ValueNode canonicalize(NotNode node, ValueNode x) { + if (x instanceof NotNode) { + return ((NotNode) x).getValue(); } - return this; + if (node != null) { + return node; + } + return new NotNode(x); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java index 06e156a8daf..9a9f2f402fb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; @@ -58,16 +59,16 @@ public final class ObjectEqualsNode extends PointerEqualsNode implements Virtual public ObjectEqualsNode(ValueNode x, ValueNode y) { super(TYPE, x, y); - assert x.stamp() instanceof AbstractObjectStamp; - assert y.stamp() instanceof AbstractObjectStamp; + assert x.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; + assert y.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; } - public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { + public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false); if (result != null) { return result; } else { - result = findSynonym(x, y); + result = findSynonym(x, y, view); if (result != null) { return result; } @@ -75,17 +76,18 @@ public final class ObjectEqualsNode extends PointerEqualsNode implements Virtual } } - public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, ValueNode x, ValueNode y) { - LogicNode result = OP.canonical(constantReflection, metaAccess, options, null, Condition.EQ, false, x, y); + public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, ValueNode x, ValueNode y, NodeView view) { + LogicNode result = OP.canonical(constantReflection, metaAccess, options, null, Condition.EQ, false, x, y, view); if (result != null) { return result; } - return create(x, y, constantReflection); + return create(x, y, constantReflection, view); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY); + NodeView view = NodeView.from(tool); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view); if (value != null) { return value; } @@ -96,25 +98,25 @@ public final class ObjectEqualsNode extends PointerEqualsNode implements Virtual @Override protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue) { + Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { ResolvedJavaType type = constantReflection.asJavaType(constant); if (type != null && nonConstant instanceof GetClassNode) { GetClassNode getClassNode = (GetClassNode) nonConstant; ValueNode object = getClassNode.getObject(); - assert ((ObjectStamp) object.stamp()).nonNull(); + assert ((ObjectStamp) object.stamp(view)).nonNull(); if (!type.isPrimitive() && (type.isConcrete() || type.isArray())) { return InstanceOfNode.create(TypeReference.createExactTrusted(type), object); } return LogicConstantNode.forBoolean(false); } - return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue); + return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue, view); } @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue) { - if (newX.stamp() instanceof ObjectStamp && newY.stamp() instanceof ObjectStamp) { + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) { + if (newX.stamp(view) instanceof ObjectStamp && newY.stamp(view) instanceof ObjectStamp) { return new ObjectEqualsNode(newX, newY); - } else if (newX.stamp() instanceof AbstractPointerStamp && newY.stamp() instanceof AbstractPointerStamp) { + } else if (newX.stamp(view) instanceof AbstractPointerStamp && newY.stamp(view) instanceof AbstractPointerStamp) { return new PointerEqualsNode(newX, newY); } throw GraalError.shouldNotReachHere(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java index 417ee0d101d..65ab3a01f23 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -50,27 +51,28 @@ public final class OrNode extends BinaryArithmeticNode implements BinaryComm super(TYPE, ArithmeticOpTable::getOr, x, y); } - public static ValueNode create(ValueNode x, ValueNode y) { - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getOr(); - Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); - ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getOr(); + Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); if (tryConstantFold != null) { return tryConstantFold; } - return canonical(null, op, stamp, x, y); + return canonical(null, op, stamp, x, y, view); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); ValueNode ret = super.canonical(tool, forX, forY); if (ret != this) { return ret; } - return canonical(this, getOp(forX, forY), stamp(), forX, forY); + return canonical(this, getOp(forX, forY), stamp(view), forX, forY, view); } - private static ValueNode canonical(OrNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY) { + private static ValueNode canonical(OrNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return forX; } @@ -90,10 +92,10 @@ public final class OrNode extends BinaryArithmeticNode implements BinaryComm return ConstantNode.forIntegerStamp(stamp, mask); } } - return reassociate(self != null ? self : (OrNode) new OrNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY); + return reassociate(self != null ? self : (OrNode) new OrNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); } if (forX instanceof NotNode && forY instanceof NotNode) { - return new NotNode(AndNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue())); + return new NotNode(AndNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue(), view)); } return self != null ? self : new OrNode(forX, forY).maybeCommuteInputs(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java index 798982d25e4..d1e399d1c13 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; @@ -56,8 +57,8 @@ public class PointerEqualsNode extends CompareNode implements BinaryCommutative< this(TYPE, x, y); } - public static LogicNode create(ValueNode x, ValueNode y) { - LogicNode result = findSynonym(x, y); + public static LogicNode create(ValueNode x, ValueNode y, NodeView view) { + LogicNode result = findSynonym(x, y, view); if (result != null) { return result; } @@ -66,13 +67,14 @@ public class PointerEqualsNode extends CompareNode implements BinaryCommutative< protected PointerEqualsNode(NodeClass c, ValueNode x, ValueNode y) { super(c, Condition.EQ, false, x, y); - assert x.stamp() instanceof AbstractPointerStamp; - assert y.stamp() instanceof AbstractPointerStamp; + assert x.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp; + assert y.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp; } @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY); + NodeView view = NodeView.from(tool); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view); if (value != null) { return value; } @@ -111,31 +113,31 @@ public class PointerEqualsNode extends CompareNode implements BinaryCommutative< @Override public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, - boolean unorderedIsTrue, ValueNode forX, ValueNode forY) { - LogicNode result = findSynonym(forX, forY); + boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { + LogicNode result = findSynonym(forX, forY, view); if (result != null) { return result; } if (isAlwaysFailingVirtualDispatchTest(condition, forX, forY)) { return LogicConstantNode.contradiction(); } - return super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY); + return super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); } @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue) { + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) { return new PointerEqualsNode(newX, newY); } } - public static LogicNode findSynonym(ValueNode forX, ValueNode forY) { + public static LogicNode findSynonym(ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return LogicConstantNode.tautology(); - } else if (forX.stamp().alwaysDistinct(forY.stamp())) { + } else if (forX.stamp(view).alwaysDistinct(forY.stamp(view))) { return LogicConstantNode.contradiction(); - } else if (((AbstractPointerStamp) forX.stamp()).alwaysNull()) { + } else if (((AbstractPointerStamp) forX.stamp(view)).alwaysNull()) { return IsNullNode.create(forY); - } else if (((AbstractPointerStamp) forY.stamp()).alwaysNull()) { + } else if (((AbstractPointerStamp) forY.stamp(view)).alwaysNull()) { return IsNullNode.create(forX); } else { return null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ReinterpretNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ReinterpretNode.java index dc5e60d39d0..b77e3c02102 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ReinterpretNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ReinterpretNode.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -56,16 +57,24 @@ public final class ReinterpretNode extends UnaryNode implements ArithmeticLIRLow public static final NodeClass TYPE = NodeClass.create(ReinterpretNode.class); - public ReinterpretNode(JavaKind to, ValueNode value) { + protected ReinterpretNode(JavaKind to, ValueNode value) { this(StampFactory.forKind(to), value); } - public ReinterpretNode(Stamp to, ValueNode value) { - super(TYPE, getReinterpretStamp(to, value.stamp()), value); + protected ReinterpretNode(Stamp to, ValueNode value) { + super(TYPE, getReinterpretStamp(to, value.stamp(NodeView.DEFAULT)), value); assert to instanceof ArithmeticStamp; } - private SerializableConstant evalConst(SerializableConstant c) { + public static ValueNode create(JavaKind to, ValueNode value, NodeView view) { + return create(StampFactory.forKind(to), value, view); + } + + public static ValueNode create(Stamp to, ValueNode value, NodeView view) { + return canonical(null, to, value, view); + } + + private static SerializableConstant evalConst(Stamp stamp, SerializableConstant c) { /* * We don't care about byte order here. Either would produce the correct result. */ @@ -73,7 +82,7 @@ public final class ReinterpretNode extends UnaryNode implements ArithmeticLIRLow c.serialize(buffer); buffer.rewind(); - SerializableConstant ret = ((ArithmeticStamp) stamp()).deserialize(buffer); + SerializableConstant ret = ((ArithmeticStamp) stamp).deserialize(buffer); assert !buffer.hasRemaining(); return ret; @@ -81,17 +90,22 @@ public final class ReinterpretNode extends UnaryNode implements ArithmeticLIRLow @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + NodeView view = NodeView.from(tool); + return canonical(this, this.stamp(view), forValue, view); + } + + public static ValueNode canonical(ReinterpretNode node, Stamp forStamp, ValueNode forValue, NodeView view) { if (forValue.isConstant()) { - return ConstantNode.forConstant(stamp(), evalConst((SerializableConstant) forValue.asConstant()), null); + return ConstantNode.forConstant(forStamp, evalConst(forStamp, (SerializableConstant) forValue.asConstant()), null); } - if (stamp().isCompatible(forValue.stamp())) { + if (forStamp.isCompatible(forValue.stamp(view))) { return forValue; } if (forValue instanceof ReinterpretNode) { ReinterpretNode reinterpret = (ReinterpretNode) forValue; - return new ReinterpretNode(stamp(), reinterpret.getValue()); + return new ReinterpretNode(forStamp, reinterpret.getValue()); } - return this; + return node != null ? node : new ReinterpretNode(forStamp, forValue); } /** @@ -269,12 +283,12 @@ public final class ReinterpretNode extends UnaryNode implements ArithmeticLIRLow @Override public boolean inferStamp() { - return updateStamp(getReinterpretStamp(stamp(), getValue().stamp())); + return updateStamp(getReinterpretStamp(stamp(NodeView.DEFAULT), getValue().stamp(NodeView.DEFAULT))); } @Override public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) { - LIRKind kind = builder.getLIRGeneratorTool().getLIRKind(stamp()); + LIRKind kind = builder.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); builder.setResult(this, gen.emitReinterpret(kind, builder.operand(getValue()))); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RemNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RemNode.java index 3ef7eebb6b8..54201e79071 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RemNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RemNode.java @@ -25,10 +25,14 @@ package org.graalvm.compiler.nodes.calc; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_32; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; +import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Rem; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -39,7 +43,7 @@ public class RemNode extends BinaryArithmeticNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(RemNode.class); - public RemNode(ValueNode x, ValueNode y) { + protected RemNode(ValueNode x, ValueNode y) { this(TYPE, x, y); } @@ -47,6 +51,16 @@ public class RemNode extends BinaryArithmeticNode implements Lowerable { super(c, ArithmeticOpTable::getRem, x, y); } + public static ValueNode create(ValueNode forX, ValueNode forY, NodeView view) { + BinaryOp op = ArithmeticOpTable.forStamp(forX.stamp(view)).getRem(); + Stamp stamp = op.foldStamp(forX.stamp(view), forY.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, forX, forY, stamp, view); + if (tryConstantFold != null) { + return tryConstantFold; + } + return new RemNode(forX, forY); + } + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java index 7b5661b698b..621cb865afc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -45,30 +46,31 @@ public final class RightShiftNode extends ShiftNode { super(TYPE, ArithmeticOpTable::getShr, x, y); } - public static ValueNode create(ValueNode x, ValueNode y) { - ArithmeticOpTable.ShiftOp op = ArithmeticOpTable.forStamp(x.stamp()).getShr(); - Stamp stamp = op.foldStamp(x.stamp(), (IntegerStamp) y.stamp()); - ValueNode value = ShiftNode.canonical(op, stamp, x, y); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + ArithmeticOpTable.ShiftOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getShr(); + Stamp stamp = op.foldStamp(x.stamp(view), (IntegerStamp) y.stamp(view)); + ValueNode value = ShiftNode.canonical(op, stamp, x, y, view); if (value != null) { return value; } - return canonical(null, op, stamp, x, y); + return canonical(null, op, stamp, x, y, view); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); ValueNode ret = super.canonical(tool, forX, forY); if (ret != this) { return ret; } - return canonical(this, getArithmeticOp(), stamp(), forX, forY); + return canonical(this, getArithmeticOp(), stamp(view), forX, forY, view); } - private static ValueNode canonical(RightShiftNode rightShiftNode, ArithmeticOpTable.ShiftOp op, Stamp stamp, ValueNode forX, ValueNode forY) { + private static ValueNode canonical(RightShiftNode rightShiftNode, ArithmeticOpTable.ShiftOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { RightShiftNode self = rightShiftNode; - if (forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) { + if (forX.stamp(view) instanceof IntegerStamp && ((IntegerStamp) forX.stamp(view)).isPositive()) { return new UnsignedRightShiftNode(forX, forY); } @@ -87,8 +89,8 @@ public final class RightShiftNode extends ShiftNode { if (other instanceof RightShiftNode) { int total = amount + otherAmount; if (total != (total & mask)) { - assert other.getX().stamp() instanceof IntegerStamp; - IntegerStamp istamp = (IntegerStamp) other.getX().stamp(); + assert other.getX().stamp(view) instanceof IntegerStamp; + IntegerStamp istamp = (IntegerStamp) other.getX().stamp(view); if (istamp.isPositive()) { return ConstantNode.forIntegerKind(stamp.getStackKind(), 0); @@ -131,7 +133,7 @@ public final class RightShiftNode extends ShiftNode { * are all equal to the sign bit of the input. That's equivalent to the condition that * the input is in the signed range of the narrow type. */ - IntegerStamp inputStamp = (IntegerStamp) getX().stamp(); + IntegerStamp inputStamp = (IntegerStamp) getX().stamp(NodeView.DEFAULT); return CodeUtil.minValue(resultBits) <= inputStamp.lowerBound() && inputStamp.upperBound() <= CodeUtil.maxValue(resultBits); } else { return false; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java index 1e997bc5b8d..062a861f828 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ArithmeticOperation; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -64,13 +65,13 @@ public abstract class ShiftNode extends BinaryNode implements ArithmeticOper * @param s the second input value */ protected ShiftNode(NodeClass> c, SerializableShiftFunction getOp, ValueNode x, ValueNode s) { - super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), (IntegerStamp) s.stamp()), x, s); - assert ((IntegerStamp) s.stamp()).getBits() == 32; + super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp(NodeView.DEFAULT))).foldStamp(x.stamp(NodeView.DEFAULT), (IntegerStamp) s.stamp(NodeView.DEFAULT)), x, s); + assert ((IntegerStamp) s.stamp(NodeView.DEFAULT)).getBits() == 32; this.getOp = getOp; } protected final ShiftOp getOp(ValueNode forValue) { - return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp())); + return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT))); } @Override @@ -85,14 +86,16 @@ public abstract class ShiftNode extends BinaryNode implements ArithmeticOper @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode valueNode = canonical(getOp(forX), stamp(), forX, forY); + NodeView view = NodeView.from(tool); + ValueNode valueNode = canonical(getOp(forX), stamp(NodeView.DEFAULT), forX, forY, view); if (valueNode != null) { return valueNode; } return this; } - public static ValueNode canonical(ShiftOp op, Stamp stamp, ValueNode forX, ValueNode forY) { + @SuppressWarnings("unused") + public static ValueNode canonical(ShiftOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { if (forX.isConstant() && forY.isConstant()) { JavaConstant amount = forY.asJavaConstant(); assert amount.getJavaKind() == JavaKind.Int; @@ -102,7 +105,7 @@ public abstract class ShiftNode extends BinaryNode implements ArithmeticOper } public int getShiftAmountMask() { - return getArithmeticOp().getShiftAmountMask(stamp()); + return getArithmeticOp().getShiftAmountMask(stamp(NodeView.DEFAULT)); } @Override @@ -117,7 +120,7 @@ public abstract class ShiftNode extends BinaryNode implements ArithmeticOper * amount. We can narrow only if (y & wideMask) == (y & narrowMask) for all possible values * of y. */ - IntegerStamp yStamp = (IntegerStamp) getY().stamp(); + IntegerStamp yStamp = (IntegerStamp) getY().stamp(NodeView.DEFAULT); return (yStamp.upMask() & (wideMask & ~narrowMask)) == 0; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java index 65c4a7050e5..a603eda3934 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -46,25 +47,25 @@ public final class SignExtendNode extends IntegerConvertNode public static final NodeClass TYPE = NodeClass.create(SignExtendNode.class); public SignExtendNode(ValueNode input, int resultBits) { - this(input, PrimitiveStamp.getBits(input.stamp()), resultBits); - assert 0 < PrimitiveStamp.getBits(input.stamp()) && PrimitiveStamp.getBits(input.stamp()) <= resultBits; + this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits); + assert 0 < PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) && PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) <= resultBits; } public SignExtendNode(ValueNode input, int inputBits, int resultBits) { super(TYPE, ArithmeticOpTable::getSignExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); } - public static ValueNode create(ValueNode input, int resultBits) { - return create(input, PrimitiveStamp.getBits(input.stamp()), resultBits); + public static ValueNode create(ValueNode input, int resultBits, NodeView view) { + return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view); } - public static ValueNode create(ValueNode input, int inputBits, int resultBits) { - IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp()).getSignExtend(); - ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp())); + public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) { + IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getSignExtend(); + ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view))); if (synonym != null) { return synonym; } - return canonical(null, input, inputBits, resultBits); + return canonical(null, input, inputBits, resultBits, view); } @Override @@ -74,35 +75,36 @@ public final class SignExtendNode extends IntegerConvertNode @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + NodeView view = NodeView.from(tool); ValueNode ret = super.canonical(tool, forValue); if (ret != this) { return ret; } - return canonical(this, forValue, getInputBits(), getResultBits()); + return canonical(this, forValue, getInputBits(), getResultBits(), view); } - private static ValueNode canonical(SignExtendNode self, ValueNode forValue, int inputBits, int resultBits) { + private static ValueNode canonical(SignExtendNode self, ValueNode forValue, int inputBits, int resultBits, NodeView view) { if (forValue instanceof SignExtendNode) { // sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx // ==> sxxx -(sign-extend)-> ssssssss sssssxxx SignExtendNode other = (SignExtendNode) forValue; - return SignExtendNode.create(other.getValue(), other.getInputBits(), resultBits); + return SignExtendNode.create(other.getValue(), other.getInputBits(), resultBits, view); } else if (forValue instanceof ZeroExtendNode) { ZeroExtendNode other = (ZeroExtendNode) forValue; if (other.getResultBits() > other.getInputBits()) { // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx // ==> sxxx -(zero-extend)-> 00000000 0000sxxx - return ZeroExtendNode.create(other.getValue(), other.getInputBits(), resultBits); + return ZeroExtendNode.create(other.getValue(), other.getInputBits(), resultBits, view); } } - if (forValue.stamp() instanceof IntegerStamp) { - IntegerStamp inputStamp = (IntegerStamp) forValue.stamp(); + if (forValue.stamp(view) instanceof IntegerStamp) { + IntegerStamp inputStamp = (IntegerStamp) forValue.stamp(view); if ((inputStamp.upMask() & (1L << (inputBits - 1))) == 0L) { // 0xxx -(sign-extend)-> 0000 0xxx // ==> 0xxx -(zero-extend)-> 0000 0xxx - return ZeroExtendNode.create(forValue, inputBits, resultBits); + return ZeroExtendNode.create(forValue, inputBits, resultBits, view); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java index c8ba664abad..dc206008f60 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java @@ -24,10 +24,12 @@ package org.graalvm.compiler.nodes.calc; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.PrimitiveStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -39,31 +41,42 @@ public class SignedDivNode extends IntegerDivRemNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(SignedDivNode.class); - public SignedDivNode(ValueNode x, ValueNode y) { + protected SignedDivNode(ValueNode x, ValueNode y) { this(TYPE, x, y); } protected SignedDivNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, IntegerStamp.OPS.getDiv().foldStamp(x.stamp(), y.stamp()), Op.DIV, Type.SIGNED, x, y); + super(c, IntegerStamp.OPS.getDiv().foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), Op.DIV, Type.SIGNED, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + return canonical(null, x, y, view); } @Override public boolean inferStamp() { - return updateStamp(IntegerStamp.OPS.getDiv().foldStamp(getX().stamp(), getY().stamp())); + return updateStamp(IntegerStamp.OPS.getDiv().foldStamp(getX().stamp(NodeView.DEFAULT), getY().stamp(NodeView.DEFAULT))); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); + return canonical(this, forX, forY, view); + } + + public static ValueNode canonical(SignedDivNode self, ValueNode forX, ValueNode forY, NodeView view) { + Stamp predictedStamp = IntegerStamp.OPS.getDiv().foldStamp(forX.stamp(NodeView.DEFAULT), forY.stamp(NodeView.DEFAULT)); + Stamp stamp = self != null ? self.stamp(view) : predictedStamp; if (forX.isConstant() && forY.isConstant()) { - @SuppressWarnings("hiding") long y = forY.asJavaConstant().asLong(); if (y == 0) { - return this; // this will trap, can not canonicalize + return self != null ? self : new SignedDivNode(forX, forY); // this will trap, can + // not canonicalize } - return ConstantNode.forIntegerStamp(stamp(), forX.asJavaConstant().asLong() / y); + return ConstantNode.forIntegerStamp(stamp, forX.asJavaConstant().asLong() / y); } else if (forY.isConstant()) { long c = forY.asJavaConstant().asLong(); - ValueNode v = canonical(forX, c); + ValueNode v = canonical(forX, c, view); if (v != null) { return v; } @@ -74,47 +87,47 @@ public class SignedDivNode extends IntegerDivRemNode implements LIRLowerable { SubNode integerSubNode = (SubNode) forX; if (integerSubNode.getY() instanceof SignedRemNode) { SignedRemNode integerRemNode = (SignedRemNode) integerSubNode.getY(); - if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.getX() == integerRemNode.getX() && + if (integerSubNode.stamp(view).isCompatible(stamp) && integerRemNode.stamp(view).isCompatible(stamp) && integerSubNode.getX() == integerRemNode.getX() && forY == integerRemNode.getY()) { SignedDivNode sd = new SignedDivNode(integerSubNode.getX(), forY); - sd.stateBefore = this.stateBefore; + sd.stateBefore = self != null ? self.stateBefore : null; return sd; } } } - if (next() instanceof SignedDivNode) { - NodeClass nodeClass = getNodeClass(); - if (next().getClass() == this.getClass() && nodeClass.equalInputs(this, next()) && valueEquals(next())) { - return next(); + if (self != null && self.next() instanceof SignedDivNode) { + NodeClass nodeClass = self.getNodeClass(); + if (self.next().getClass() == self.getClass() && nodeClass.equalInputs(self, self.next()) && self.valueEquals(self.next())) { + return self.next(); } } - return this; + return self != null ? self : new SignedDivNode(forX, forY); } - public static ValueNode canonical(ValueNode forX, long c) { + public static ValueNode canonical(ValueNode forX, long c, NodeView view) { if (c == 1) { return forX; } if (c == -1) { - return NegateNode.create(forX); + return NegateNode.create(forX, view); } long abs = Math.abs(c); - if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) { + if (CodeUtil.isPowerOf2(abs) && forX.stamp(view) instanceof IntegerStamp) { ValueNode dividend = forX; - IntegerStamp stampX = (IntegerStamp) forX.stamp(); + IntegerStamp stampX = (IntegerStamp) forX.stamp(view); int log2 = CodeUtil.log2(abs); // no rounding if dividend is positive or if its low bits are always 0 if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) { - int bits = PrimitiveStamp.getBits(forX.stamp()); + int bits = PrimitiveStamp.getBits(forX.stamp(view)); RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1)); UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2)); - dividend = BinaryArithmeticNode.add(dividend, round); + dividend = BinaryArithmeticNode.add(dividend, round, view); } RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2)); if (c < 0) { - return NegateNode.create(shift); + return NegateNode.create(shift, view); } return shift; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java index 4dbfd845b54..432cb047cd2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java @@ -23,10 +23,12 @@ package org.graalvm.compiler.nodes.calc; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -38,52 +40,63 @@ public class SignedRemNode extends IntegerDivRemNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(SignedRemNode.class); - public SignedRemNode(ValueNode x, ValueNode y) { + protected SignedRemNode(ValueNode x, ValueNode y) { this(TYPE, x, y); } protected SignedRemNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, IntegerStamp.OPS.getRem().foldStamp(x.stamp(), y.stamp()), Op.REM, Type.SIGNED, x, y); + super(c, IntegerStamp.OPS.getRem().foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), Op.REM, Type.SIGNED, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + Stamp stamp = IntegerStamp.OPS.getRem().foldStamp(x.stamp(view), y.stamp(view)); + return canonical(null, x, y, stamp, view); } @Override public boolean inferStamp() { - return updateStamp(IntegerStamp.OPS.getRem().foldStamp(getX().stamp(), getY().stamp())); + return updateStamp(IntegerStamp.OPS.getRem().foldStamp(getX().stamp(NodeView.DEFAULT), getY().stamp(NodeView.DEFAULT))); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); + return canonical(this, forX, forY, stamp(view), view); + } + + private static ValueNode canonical(SignedRemNode self, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { if (forX.isConstant() && forY.isConstant()) { - @SuppressWarnings("hiding") long y = forY.asJavaConstant().asLong(); if (y == 0) { - return this; // this will trap, can not canonicalize + return self != null ? self : new SignedRemNode(forX, forY); // this will trap, can + // not canonicalize } - return ConstantNode.forIntegerStamp(stamp(), forX.asJavaConstant().asLong() % y); - } else if (forY.isConstant() && forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { + return ConstantNode.forIntegerStamp(stamp, forX.asJavaConstant().asLong() % y); + } else if (forY.isConstant() && forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) { long constY = forY.asJavaConstant().asLong(); - IntegerStamp xStamp = (IntegerStamp) forX.stamp(); - IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + IntegerStamp xStamp = (IntegerStamp) forX.stamp(view); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(view); if (constY < 0 && constY != CodeUtil.minValue(yStamp.getBits())) { - return new SignedRemNode(forX, ConstantNode.forIntegerStamp(yStamp, -constY)).canonical(tool); + Stamp newStamp = IntegerStamp.OPS.getRem().foldStamp(forX.stamp(view), forY.stamp(view)); + return canonical(null, forX, ConstantNode.forIntegerStamp(yStamp, -constY), newStamp, view); } if (constY == 1) { - return ConstantNode.forIntegerStamp(stamp(), 0); + return ConstantNode.forIntegerStamp(stamp, 0); } else if (CodeUtil.isPowerOf2(constY)) { if (xStamp.isPositive()) { // x & (y - 1) - return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), constY - 1)); + return new AndNode(forX, ConstantNode.forIntegerStamp(stamp, constY - 1)); } else if (xStamp.isNegative()) { // -((-x) & (y - 1)) - return new NegateNode(new AndNode(new NegateNode(forX), ConstantNode.forIntegerStamp(stamp(), constY - 1))); + return new NegateNode(new AndNode(new NegateNode(forX), ConstantNode.forIntegerStamp(stamp, constY - 1))); } else { // x - ((x / y) << log2(y)) - return SubNode.create(forX, LeftShiftNode.create(SignedDivNode.canonical(forX, constY), ConstantNode.forInt(CodeUtil.log2(constY)))); + return SubNode.create(forX, LeftShiftNode.create(SignedDivNode.canonical(forX, constY, view), ConstantNode.forInt(CodeUtil.log2(constY)), view), view); } } } - return this; + return self != null ? self : new SignedRemNode(forX, forY); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SqrtNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SqrtNode.java index 8b400619d2a..ae80f135ca4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SqrtNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SqrtNode.java @@ -30,6 +30,8 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -42,10 +44,18 @@ public final class SqrtNode extends UnaryArithmeticNode implements Arithme public static final NodeClass TYPE = NodeClass.create(SqrtNode.class); - public SqrtNode(ValueNode x) { + protected SqrtNode(ValueNode x) { super(TYPE, ArithmeticOpTable::getSqrt, x); } + public static ValueNode create(ValueNode x, NodeView view) { + if (x.isConstant()) { + ArithmeticOpTable.UnaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getSqrt(); + return ConstantNode.forPrimitive(op.foldStamp(x.stamp(view)), op.foldConstant(x.asConstant())); + } + return new SqrtNode(x); + } + @Override public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) { nodeValueMap.setResult(this, gen.emitMathSqrt(nodeValueMap.operand(getValue()))); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java index bfeca0be95c..f6fe0ab5e4c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -53,20 +54,20 @@ public class SubNode extends BinaryArithmeticNode implements NarrowableArit super(c, ArithmeticOpTable::getSub, x, y); } - public static ValueNode create(ValueNode x, ValueNode y) { - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getSub(); - Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); - ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getSub(); + Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); if (tryConstantFold != null) { return tryConstantFold; } - return canonical(null, op, stamp, x, y); + return canonical(null, op, stamp, x, y, view); } - private static ValueNode canonical(SubNode subNode, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY) { + private static ValueNode canonical(SubNode subNode, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { SubNode self = subNode; if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - Constant zero = op.getZero(forX.stamp()); + Constant zero = op.getZero(forX.stamp(view)); if (zero != null) { return ConstantNode.forPrimitive(stamp, zero); } @@ -87,18 +88,18 @@ public class SubNode extends BinaryArithmeticNode implements NarrowableArit SubNode x = (SubNode) forX; if (x.getX() == forY) { // (a - b) - a - return NegateNode.create(x.getY()); + return NegateNode.create(x.getY(), view); } } if (forY instanceof AddNode) { AddNode y = (AddNode) forY; if (y.getX() == forX) { // a - (a + b) - return NegateNode.create(y.getY()); + return NegateNode.create(y.getY(), view); } if (y.getY() == forX) { // b - (a + b) - return NegateNode.create(y.getX()); + return NegateNode.create(y.getX(), view); } } else if (forY instanceof SubNode) { SubNode y = (SubNode) forY; @@ -114,7 +115,7 @@ public class SubNode extends BinaryArithmeticNode implements NarrowableArit return forX; } if (associative && self != null) { - ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY); + ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY, view); if (reassociated != self) { return reassociated; } @@ -124,7 +125,7 @@ public class SubNode extends BinaryArithmeticNode implements NarrowableArit if (i < 0 || ((IntegerStamp) StampFactory.forKind(forY.getStackKind())).contains(-i)) { // Adding a negative is more friendly to the backend since adds are // commutative, so prefer add when it fits. - return BinaryArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp, -i)); + return BinaryArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp, -i), view); } } } else if (forX.isConstant()) { @@ -135,30 +136,28 @@ public class SubNode extends BinaryArithmeticNode implements NarrowableArit * have to test for the neutral element of +, because we are doing this * transformation: 0 - x == (-x) + 0 == -x. */ - return NegateNode.create(forY); + return NegateNode.create(forY, view); } if (associative && self != null) { - return reassociate(self, ValueNode.isConstantPredicate(), forX, forY); + return reassociate(self, ValueNode.isConstantPredicate(), forX, forY, view); } } if (forY instanceof NegateNode) { - return BinaryArithmeticNode.add(forX, ((NegateNode) forY).getValue()); + return BinaryArithmeticNode.add(forX, ((NegateNode) forY).getValue(), view); } - if (self == null) { - self = new SubNode(forX, forY); - } - return self; + return self != null ? self : new SubNode(forX, forY); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); ValueNode ret = super.canonical(tool, forX, forY); if (ret != this) { return ret; } BinaryOp op = getOp(forX, forY); - return canonical(this, op, stamp, forX, forY); + return canonical(this, op, stamp, forX, forY, view); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryArithmeticNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryArithmeticNode.java index 7f3d019888b..d2f0418d6d8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryArithmeticNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryArithmeticNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ArithmeticOperation; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -47,12 +48,12 @@ public abstract class UnaryArithmeticNode extends UnaryNode implements Arith protected final SerializableUnaryFunction getOp; protected UnaryArithmeticNode(NodeClass> c, SerializableUnaryFunction getOp, ValueNode value) { - super(c, getOp.apply(ArithmeticOpTable.forStamp(value.stamp())).foldStamp(value.stamp()), value); + super(c, getOp.apply(ArithmeticOpTable.forStamp(value.stamp(NodeView.DEFAULT))).foldStamp(value.stamp(NodeView.DEFAULT)), value); this.getOp = getOp; } protected final UnaryOp getOp(ValueNode forValue) { - return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp())); + return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT))); } @Override @@ -62,7 +63,7 @@ public abstract class UnaryArithmeticNode extends UnaryNode implements Arith @Override public Stamp foldStamp(Stamp newStamp) { - assert newStamp.isCompatible(getValue().stamp()); + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); return getOp(getValue()).foldStamp(newStamp); } @@ -77,7 +78,7 @@ public abstract class UnaryArithmeticNode extends UnaryNode implements Arith protected static ValueNode findSynonym(ValueNode forValue, UnaryOp op) { if (forValue.isConstant()) { - return ConstantNode.forPrimitive(op.foldStamp(forValue.stamp()), op.foldConstant(forValue.asConstant())); + return ConstantNode.forPrimitive(op.foldStamp(forValue.stamp(NodeView.DEFAULT)), op.foldConstant(forValue.asConstant())); } return null; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryNode.java index 66a8ee32342..e09f50788a2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryNode.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; /** @@ -63,7 +64,7 @@ public abstract class UnaryNode extends FloatingNode implements Canonicalizable. @Override public boolean inferStamp() { - return updateStamp(foldStamp(value.stamp())); + return updateStamp(foldStamp(value.stamp(NodeView.DEFAULT))); } /** @@ -74,6 +75,6 @@ public abstract class UnaryNode extends FloatingNode implements Canonicalizable. * @param newStamp */ public Stamp foldStamp(Stamp newStamp) { - return stamp(); + return stamp(NodeView.DEFAULT); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnpackEndianHalfNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnpackEndianHalfNode.java index ad7cfdc9932..dadd326bf12 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnpackEndianHalfNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnpackEndianHalfNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -52,7 +53,8 @@ public final class UnpackEndianHalfNode extends UnaryNode implements Lowerable { this.firstHalf = firstHalf; } - public static ValueNode create(ValueNode value, boolean firstHalf) { + @SuppressWarnings("unused") + public static ValueNode create(ValueNode value, boolean firstHalf, NodeView view) { if (value.isConstant() && value.asConstant().isDefaultForKind()) { return ConstantNode.defaultForKind(JavaKind.Int); } @@ -84,7 +86,7 @@ public final class UnpackEndianHalfNode extends UnaryNode implements Lowerable { if ((byteOrder == ByteOrder.BIG_ENDIAN) == firstHalf) { result = graph().unique(new UnsignedRightShiftNode(result, ConstantNode.forInt(32, graph()))); } - result = IntegerConvertNode.convert(result, StampFactory.forKind(JavaKind.Int), graph()); + result = IntegerConvertNode.convert(result, StampFactory.forKind(JavaKind.Int), graph(), NodeView.DEFAULT); replaceAtUsagesAndDelete(result); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedDivNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedDivNode.java index 313407800a8..792e4388a5d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedDivNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedDivNode.java @@ -23,10 +23,12 @@ package org.graalvm.compiler.nodes.calc; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -43,18 +45,30 @@ public class UnsignedDivNode extends IntegerDivRemNode implements LIRLowerable { } protected UnsignedDivNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, x.stamp().unrestricted(), Op.DIV, Type.UNSIGNED, x, y); + super(c, x.stamp(NodeView.DEFAULT).unrestricted(), Op.DIV, Type.UNSIGNED, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + Stamp stamp = x.stamp(view).unrestricted(); + return canonical(null, x, y, stamp, view); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - int bits = ((IntegerStamp) stamp()).getBits(); + NodeView view = NodeView.from(tool); + return canonical(this, forX, forY, stamp(view), view); + } + + @SuppressWarnings("unused") + private static ValueNode canonical(UnsignedDivNode self, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { + int bits = ((IntegerStamp) stamp).getBits(); if (forX.isConstant() && forY.isConstant()) { long yConst = CodeUtil.zeroExtend(forY.asJavaConstant().asLong(), bits); if (yConst == 0) { - return this; // this will trap, cannot canonicalize + return self != null ? self : new UnsignedDivNode(forX, forY); // this will trap, + // cannot canonicalize } - return ConstantNode.forIntegerStamp(stamp(), Long.divideUnsigned(CodeUtil.zeroExtend(forX.asJavaConstant().asLong(), bits), yConst)); + return ConstantNode.forIntegerStamp(stamp, Long.divideUnsigned(CodeUtil.zeroExtend(forX.asJavaConstant().asLong(), bits), yConst)); } else if (forY.isConstant()) { long c = CodeUtil.zeroExtend(forY.asJavaConstant().asLong(), bits); if (c == 1) { @@ -64,7 +78,7 @@ public class UnsignedDivNode extends IntegerDivRemNode implements LIRLowerable { return new UnsignedRightShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(c))); } } - return this; + return self != null ? self : new UnsignedDivNode(forX, forY); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRemNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRemNode.java index 849324c4263..bfba2c43283 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRemNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRemNode.java @@ -23,10 +23,12 @@ package org.graalvm.compiler.nodes.calc; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -43,27 +45,39 @@ public class UnsignedRemNode extends IntegerDivRemNode implements LIRLowerable { } protected UnsignedRemNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, x.stamp().unrestricted(), Op.REM, Type.UNSIGNED, x, y); + super(c, x.stamp(NodeView.DEFAULT).unrestricted(), Op.REM, Type.UNSIGNED, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + Stamp stamp = x.stamp(view).unrestricted(); + return canonical(null, x, y, stamp, view); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - int bits = ((IntegerStamp) stamp()).getBits(); + NodeView view = NodeView.from(tool); + return canonical(this, forX, forY, stamp(view), view); + } + + @SuppressWarnings("unused") + public static ValueNode canonical(UnsignedRemNode self, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { + int bits = ((IntegerStamp) stamp).getBits(); if (forX.isConstant() && forY.isConstant()) { long yConst = CodeUtil.zeroExtend(forY.asJavaConstant().asLong(), bits); if (yConst == 0) { - return this; // this will trap, cannot canonicalize + return self != null ? self : new UnsignedRemNode(forX, forY); // this will trap, + // cannot canonicalize } - return ConstantNode.forIntegerStamp(stamp(), Long.remainderUnsigned(CodeUtil.zeroExtend(forX.asJavaConstant().asLong(), bits), yConst)); + return ConstantNode.forIntegerStamp(stamp, Long.remainderUnsigned(CodeUtil.zeroExtend(forX.asJavaConstant().asLong(), bits), yConst)); } else if (forY.isConstant()) { long c = CodeUtil.zeroExtend(forY.asJavaConstant().asLong(), bits); if (c == 1) { - return ConstantNode.forIntegerStamp(stamp(), 0); + return ConstantNode.forIntegerStamp(stamp, 0); } else if (CodeUtil.isPowerOf2(c)) { - return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1)); + return new AndNode(forX, ConstantNode.forIntegerStamp(stamp, c - 1)); } } - return this; + return self != null ? self : new UnsignedRemNode(forX, forY); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java index 7845b059401..7edf7d4ec20 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java @@ -25,11 +25,13 @@ package org.graalvm.compiler.nodes.calc; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.UShr; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -44,17 +46,34 @@ public final class UnsignedRightShiftNode extends ShiftNode { super(TYPE, ArithmeticOpTable::getUShr, x, y); } + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + ArithmeticOpTable.ShiftOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getUShr(); + Stamp stamp = op.foldStamp(x.stamp(view), (IntegerStamp) y.stamp(view)); + ValueNode value = ShiftNode.canonical(op, stamp, x, y, view); + if (value != null) { + return value; + } + + return canonical(null, op, stamp, x, y, view); + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); ValueNode ret = super.canonical(tool, forX, forY); if (ret != this) { return ret; } + return canonical(this, this.getArithmeticOp(), this.stamp(view), forX, forY, view); + } + + @SuppressWarnings("unused") + private static ValueNode canonical(UnsignedRightShiftNode node, ArithmeticOpTable.ShiftOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { if (forY.isConstant()) { int amount = forY.asJavaConstant().asInt(); int originalAmout = amount; - int mask = getShiftAmountMask(); + int mask = op.getShiftAmountMask(stamp); amount &= mask; if (amount == 0) { return forX; @@ -66,14 +85,14 @@ public final class UnsignedRightShiftNode extends ShiftNode { if (other instanceof UnsignedRightShiftNode) { int total = amount + otherAmount; if (total != (total & mask)) { - return ConstantNode.forIntegerKind(getStackKind(), 0); + return ConstantNode.forIntegerKind(stamp.getStackKind(), 0); } return new UnsignedRightShiftNode(other.getX(), ConstantNode.forInt(total)); } else if (other instanceof LeftShiftNode && otherAmount == amount) { - if (getStackKind() == JavaKind.Long) { + if (stamp.getStackKind() == JavaKind.Long) { return new AndNode(other.getX(), ConstantNode.forLong(-1L >>> amount)); } else { - assert getStackKind() == JavaKind.Int; + assert stamp.getStackKind() == JavaKind.Int; return new AndNode(other.getX(), ConstantNode.forInt(-1 >>> amount)); } } @@ -83,7 +102,11 @@ public final class UnsignedRightShiftNode extends ShiftNode { return new UnsignedRightShiftNode(forX, ConstantNode.forInt(amount)); } } - return this; + + if (node != null) { + return node; + } + return new UnsignedRightShiftNode(forX, forY); } @Override @@ -98,7 +121,7 @@ public final class UnsignedRightShiftNode extends ShiftNode { * For unsigned right shifts, the narrow can be done before the shift if the cut off * bits are all zero. */ - IntegerStamp inputStamp = (IntegerStamp) getX().stamp(); + IntegerStamp inputStamp = (IntegerStamp) getX().stamp(NodeView.DEFAULT); return (inputStamp.upMask() & ~(resultBits - 1)) == 0; } else { return false; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java index 93d33ada9f2..a204f24d93c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -48,17 +49,17 @@ public final class XorNode extends BinaryArithmeticNode implements BinaryCo public XorNode(ValueNode x, ValueNode y) { super(TYPE, ArithmeticOpTable::getXor, x, y); - assert x.stamp().isCompatible(y.stamp()); + assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)); } - public static ValueNode create(ValueNode x, ValueNode y) { - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getXor(); - Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); - ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getXor(); + Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); if (tryConstantFold != null) { return tryConstantFold; } - return canonical(null, op, stamp, x, y); + return canonical(null, op, stamp, x, y, view); } @Override @@ -68,12 +69,13 @@ public final class XorNode extends BinaryArithmeticNode implements BinaryCo return ret; } - return canonical(this, getOp(forX, forY), stamp(), forX, forY); + NodeView view = NodeView.from(tool); + return canonical(this, getOp(forX, forY), stamp(NodeView.DEFAULT), forX, forY, view); } - private static ValueNode canonical(XorNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY) { + private static ValueNode canonical(XorNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return ConstantNode.forPrimitive(stamp, op.getZero(forX.stamp())); + return ConstantNode.forPrimitive(stamp, op.getZero(forX.stamp(view))); } if (forX.isConstant() && !forY.isConstant()) { return new XorNode(forY, forX); @@ -91,7 +93,7 @@ public final class XorNode extends BinaryArithmeticNode implements BinaryCo return new NotNode(forX); } } - return reassociate(self != null ? self : (XorNode) new XorNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY); + return reassociate(self != null ? self : (XorNode) new XorNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); } return self != null ? self : new XorNode(forX, forY).maybeCommuteInputs(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java index 83b5b3a4471..8574c816fca 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -50,25 +51,25 @@ public final class ZeroExtendNode extends IntegerConvertNode public static final NodeClass TYPE = NodeClass.create(ZeroExtendNode.class); public ZeroExtendNode(ValueNode input, int resultBits) { - this(input, PrimitiveStamp.getBits(input.stamp()), resultBits); - assert 0 < PrimitiveStamp.getBits(input.stamp()) && PrimitiveStamp.getBits(input.stamp()) <= resultBits; + this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits); + assert 0 < PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) && PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) <= resultBits; } public ZeroExtendNode(ValueNode input, int inputBits, int resultBits) { super(TYPE, ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); } - public static ValueNode create(ValueNode input, int resultBits) { - return create(input, PrimitiveStamp.getBits(input.stamp()), resultBits); + public static ValueNode create(ValueNode input, int resultBits, NodeView view) { + return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view); } - public static ValueNode create(ValueNode input, int inputBits, int resultBits) { - IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp()).getZeroExtend(); - ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp())); + public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) { + IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getZeroExtend(); + ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view))); if (synonym != null) { return synonym; } - return canonical(null, input, inputBits, resultBits); + return canonical(null, input, inputBits, resultBits, view); } @Override @@ -91,15 +92,16 @@ public final class ZeroExtendNode extends IntegerConvertNode @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + NodeView view = NodeView.from(tool); ValueNode ret = super.canonical(tool, forValue); if (ret != this) { return ret; } - return canonical(this, forValue, getInputBits(), getResultBits()); + return canonical(this, forValue, getInputBits(), getResultBits(), view); } - private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits) { + private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits, NodeView view) { ZeroExtendNode self = zeroExtendNode; if (forValue instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx @@ -109,20 +111,20 @@ public final class ZeroExtendNode extends IntegerConvertNode } if (forValue instanceof NarrowNode) { NarrowNode narrow = (NarrowNode) forValue; - Stamp inputStamp = narrow.getValue().stamp(); + Stamp inputStamp = narrow.getValue().stamp(view); if (inputStamp instanceof IntegerStamp) { IntegerStamp istamp = (IntegerStamp) inputStamp; - long mask = CodeUtil.mask(PrimitiveStamp.getBits(narrow.stamp())); + long mask = CodeUtil.mask(PrimitiveStamp.getBits(narrow.stamp(view))); if ((istamp.upMask() & ~mask) == 0) { // The original value cannot change because of the narrow and zero extend. if (istamp.getBits() < resultBits) { // Need to keep the zero extend, skip the narrow. - return create(narrow.getValue(), resultBits); + return create(narrow.getValue(), resultBits, view); } else if (istamp.getBits() > resultBits) { // Need to keep the narrow, skip the zero extend. - return NarrowNode.create(narrow.getValue(), resultBits); + return NarrowNode.create(narrow.getValue(), resultBits, view); } else { assert istamp.getBits() == resultBits; // Just return the original value. diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/BlackholeNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/BlackholeNode.java index 300ac616bae..0dbce573cab 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/BlackholeNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/BlackholeNode.java @@ -44,6 +44,10 @@ public final class BlackholeNode extends FixedWithNextNode implements LIRLowerab this.value = value; } + public ValueNode getValue() { + return value; + } + @Override public void generate(NodeLIRBuilderTool gen) { gen.getLIRGeneratorTool().emitBlackhole(gen.operand(value)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/OpaqueNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/OpaqueNode.java index 62b564f2c38..cf5ee474356 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/OpaqueNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/OpaqueNode.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -39,7 +40,7 @@ public final class OpaqueNode extends FloatingNode implements LIRLowerable { @Input protected ValueNode value; public OpaqueNode(ValueNode value) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp(NodeView.DEFAULT).unrestricted()); this.value = value; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java index 38376fbf6cb..02cb3b8f607 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -90,7 +91,7 @@ public class BoxNode extends FixedWithNextNode implements VirtualizableAllocatio } protected VirtualBoxingNode createVirtualBoxingNode() { - return new VirtualBoxingNode(StampTool.typeOrNull(stamp()), boxingKind); + return new VirtualBoxingNode(StampTool.typeOrNull(stamp(NodeView.DEFAULT)), boxingKind); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java index cc3e63d14f8..e6f436d5729 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; @@ -67,7 +68,7 @@ public final class BranchProbabilityNode extends FloatingNode implements Simplif @Input ValueNode condition; public BranchProbabilityNode(ValueNode probability, ValueNode condition) { - super(TYPE, condition.stamp()); + super(TYPE, condition.stamp(NodeView.DEFAULT)); this.probability = probability; this.condition = condition; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java index b490e846ba1..6fef3a662d9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -46,7 +47,7 @@ public class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowera } protected FixedValueAnchorNode(NodeClass c, ValueNode object) { - super(c, object.stamp()); + super(c, object.stamp(NodeView.DEFAULT)); this.object = object; } @@ -63,7 +64,7 @@ public class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowera @Override public boolean inferStamp() { if (predefinedStamp == null) { - return updateStamp(object.stamp()); + return updateStamp(object.stamp(NodeView.DEFAULT)); } else { return false; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GetClassNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GetClassNode.java index 15f73937b12..43f17e9462e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GetClassNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GetClassNode.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -60,7 +61,7 @@ public final class GetClassNode extends FloatingNode implements Lowerable, Canon public GetClassNode(Stamp stamp, ValueNode object) { super(TYPE, stamp); this.object = object; - assert ((ObjectStamp) object.stamp()).nonNull(); + assert ((ObjectStamp) object.stamp(NodeView.DEFAULT)).nonNull(); } @Override @@ -68,9 +69,9 @@ public final class GetClassNode extends FloatingNode implements Lowerable, Canon tool.getLowerer().lower(this, tool); } - public static ValueNode tryFold(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode object) { - if (metaAccess != null && object != null && object.stamp() instanceof ObjectStamp) { - ObjectStamp objectStamp = (ObjectStamp) object.stamp(); + public static ValueNode tryFold(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, NodeView view, ValueNode object) { + if (metaAccess != null && object != null && object.stamp(view) instanceof ObjectStamp) { + ObjectStamp objectStamp = (ObjectStamp) object.stamp(view); if (objectStamp.isExactType()) { return ConstantNode.forConstant(constantReflection.asJavaClass(objectStamp.type()), metaAccess); } @@ -80,7 +81,8 @@ public final class GetClassNode extends FloatingNode implements Lowerable, Canon @Override public ValueNode canonical(CanonicalizerTool tool) { - ValueNode folded = tryFold(tool.getMetaAccess(), tool.getConstantReflection(), getObject()); + NodeView view = NodeView.from(tool); + ValueNode folded = tryFold(tool.getMetaAccess(), tool.getConstantReflection(), view, getObject()); return folded == null ? this : folded; } @@ -90,7 +92,7 @@ public final class GetClassNode extends FloatingNode implements Lowerable, Canon if (alias instanceof VirtualObjectNode) { VirtualObjectNode virtual = (VirtualObjectNode) alias; Constant javaClass = tool.getConstantReflectionProvider().asJavaClass(virtual.type()); - tool.replaceWithValue(ConstantNode.forConstant(stamp(), javaClass, tool.getMetaAccessProvider(), graph())); + tool.replaceWithValue(ConstantNode.forConstant(stamp(NodeView.DEFAULT), javaClass, tool.getMetaAccessProvider(), graph())); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java index 75afb6f506f..d63cd4d311b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java @@ -43,6 +43,7 @@ import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IntegerBelowNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; @@ -70,7 +71,7 @@ public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, assert keySuccessors.length == keys.length + 1; assert keySuccessors.length == keyProbabilities.length; this.keys = keys; - assert value.stamp() instanceof PrimitiveStamp && value.stamp().getStackKind().isNumericInteger(); + assert value.stamp(NodeView.DEFAULT) instanceof PrimitiveStamp && value.stamp(NodeView.DEFAULT).getStackKind().isNumericInteger(); assert assertSorted(); } @@ -135,6 +136,7 @@ public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, @Override public void simplify(SimplifierTool tool) { + NodeView view = NodeView.from(tool); if (blockSuccessorCount() == 1) { tool.addToWorkList(defaultSuccessor()); graph().removeSplitPropagate(this, defaultSuccessor()); @@ -142,7 +144,7 @@ public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, killOtherSuccessors(tool, successorIndexAtKey(value().asJavaConstant().asInt())); } else if (tryOptimizeEnumSwitch(tool)) { return; - } else if (tryRemoveUnreachableKeys(tool, value().stamp())) { + } else if (tryRemoveUnreachableKeys(tool, value().stamp(view))) { return; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java index 1000a9e0ca9..5e19233ac26 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -61,8 +62,8 @@ public final class LoadHubNode extends FloatingNode implements Lowerable, Canoni } private static Stamp hubStamp(StampProvider stampProvider, ValueNode value) { - assert value.stamp() instanceof ObjectStamp; - return stampProvider.createHubStamp(((ObjectStamp) value.stamp())); + assert value.stamp(NodeView.DEFAULT) instanceof ObjectStamp; + return stampProvider.createHubStamp(((ObjectStamp) value.stamp(NodeView.DEFAULT))); } public static ValueNode create(ValueNode value, StampProvider stampProvider, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { @@ -91,9 +92,10 @@ public final class LoadHubNode extends FloatingNode implements Lowerable, Canoni @Override public ValueNode canonical(CanonicalizerTool tool) { if (!GeneratePIC.getValue(tool.getOptions())) { + NodeView view = NodeView.from(tool); MetaAccessProvider metaAccess = tool.getMetaAccess(); ValueNode curValue = getValue(); - ValueNode newNode = findSynonym(curValue, stamp(), metaAccess, tool.getConstantReflection()); + ValueNode newNode = findSynonym(curValue, stamp(view), metaAccess, tool.getConstantReflection()); if (newNode != null) { return newNode; } @@ -117,7 +119,7 @@ public final class LoadHubNode extends FloatingNode implements Lowerable, Canoni ValueNode alias = tool.getAlias(getValue()); TypeReference type = StampTool.typeReferenceOrNull(alias); if (type != null && type.isExact()) { - tool.replaceWithValue(ConstantNode.forConstant(stamp(), tool.getConstantReflectionProvider().asObjectHub(type.getType()), tool.getMetaAccessProvider(), graph())); + tool.replaceWithValue(ConstantNode.forConstant(stamp(NodeView.DEFAULT), tool.getConstantReflectionProvider().asObjectHub(type.getType()), tool.getMetaAccessProvider(), graph())); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadMethodNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadMethodNode.java index 85f0c218414..c0b12be3443 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadMethodNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadMethodNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -96,8 +97,9 @@ public final class LoadMethodNode extends FixedWithNextNode implements Lowerable Assumptions assumptions = graph().getAssumptions(); AssumptionResult resolvedMethod = type.getType().findUniqueConcreteMethod(method); if (resolvedMethod != null && resolvedMethod.canRecordTo(assumptions) && !type.getType().isInterface() && method.getDeclaringClass().isAssignableFrom(type.getType())) { + NodeView view = NodeView.from(tool); resolvedMethod.recordTo(assumptions); - return ConstantNode.forConstant(stamp(), resolvedMethod.getResult().getEncoding(), tool.getMetaAccess()); + return ConstantNode.forConstant(stamp(view), resolvedMethod.getResult().getEncoding(), tool.getMetaAccess()); } } } @@ -123,9 +125,9 @@ public final class LoadMethodNode extends FixedWithNextNode implements Lowerable * This really represent a misuse of LoadMethod since we're loading from a class which * isn't known to implement the original method but for now at least fold it away. */ - return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, null); + return ConstantNode.forConstant(stamp(NodeView.DEFAULT), JavaConstant.NULL_POINTER, null); } else { - return ConstantNode.forConstant(stamp(), newMethod.getEncoding(), tool.getMetaAccess()); + return ConstantNode.forConstant(stamp(NodeView.DEFAULT), newMethod.getEncoding(), tool.getMetaAccess()); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java index de715c7e2c3..6638e3f0d14 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ReinterpretNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; @@ -103,14 +104,14 @@ public class RawLoadNode extends UnsafeAccessNode implements Lowerable, Virtuali JavaKind entryKind = virtual.entryKind(entryIndex); if (entry.getStackKind() == getStackKind() || entryKind == accessKind()) { - if (!(entry.stamp().isCompatible(stamp()))) { - if (entry.stamp() instanceof PrimitiveStamp && stamp instanceof PrimitiveStamp) { + if (!(entry.stamp(NodeView.DEFAULT).isCompatible(stamp(NodeView.DEFAULT)))) { + if (entry.stamp(NodeView.DEFAULT) instanceof PrimitiveStamp && stamp instanceof PrimitiveStamp) { PrimitiveStamp p1 = (PrimitiveStamp) stamp; - PrimitiveStamp p2 = (PrimitiveStamp) entry.stamp(); + PrimitiveStamp p2 = (PrimitiveStamp) entry.stamp(NodeView.DEFAULT); int width1 = p1.getBits(); int width2 = p2.getBits(); if (width1 == width2) { - Node replacement = new ReinterpretNode(p2, entry); + Node replacement = ReinterpretNode.create(p2, entry, NodeView.DEFAULT); tool.replaceWith((ValueNode) replacement); return; } else { @@ -141,11 +142,12 @@ public class RawLoadNode extends UnsafeAccessNode implements Lowerable, Virtuali if (arrayConstant != null) { int stableDimension = objectConstant.getStableDimension(); if (stableDimension > 0) { + NodeView view = NodeView.from(tool); long constantOffset = offset().asJavaConstant().asLong(); - Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), arrayConstant, constantOffset); + Constant constant = stamp(view).readConstant(tool.getConstantReflection().getMemoryAccessProvider(), arrayConstant, constantOffset); boolean isDefaultStable = objectConstant.isDefaultStable(); if (constant != null && (isDefaultStable || !constant.isDefaultForKind())) { - return ConstantNode.forConstant(stamp(), constant, stableDimension - 1, isDefaultStable, tool.getMetaAccess()); + return ConstantNode.forConstant(stamp(view), constant, stableDimension - 1, isDefaultStable, tool.getMetaAccess()); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java index 4f9e076d4d6..14ae73e47ef 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.ControlSplitNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.meta.Constant; @@ -79,7 +80,8 @@ public abstract class SwitchNode extends ControlSplitNode { */ protected SwitchNode(NodeClass c, ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) { super(c, StampFactory.forVoid()); - assert value.stamp().getStackKind().isNumericInteger() || value.stamp() instanceof AbstractPointerStamp : value.stamp() + " key not supported by SwitchNode"; + assert value.stamp(NodeView.DEFAULT).getStackKind().isNumericInteger() || value.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp : value.stamp(NodeView.DEFAULT) + + " key not supported by SwitchNode"; assert keySuccessors.length == keyProbabilities.length; this.successors = new NodeSuccessorList<>(this, successors); this.value = value; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java index 09b4cc72c89..4fbbcef8ce8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; @@ -118,7 +119,7 @@ public interface GraphBuilderContext extends GraphBuilderTool { } default ValueNode addNonNullCast(ValueNode value) { - AbstractPointerStamp valueStamp = (AbstractPointerStamp) value.stamp(); + AbstractPointerStamp valueStamp = (AbstractPointerStamp) value.stamp(NodeView.DEFAULT); if (valueStamp.nonNull()) { return value; } else { @@ -277,7 +278,7 @@ public interface GraphBuilderContext extends GraphBuilderTool { default ValueNode nullCheckedValue(ValueNode value, DeoptimizationAction action) { if (!StampTool.isPointerNonNull(value)) { LogicNode condition = getGraph().unique(IsNullNode.create(value)); - ObjectStamp receiverStamp = (ObjectStamp) value.stamp(); + ObjectStamp receiverStamp = (ObjectStamp) value.stamp(NodeView.DEFAULT); Stamp stamp = receiverStamp.join(objectNonNull()); FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, NullCheckException, action, true)); ValueNode nonNullReceiver = getGraph().addOrUniqueWithInputs(PiNode.create(value, stamp, fixedGuard)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java index cff46027cdb..332c51053ed 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; @@ -88,6 +89,6 @@ public abstract class AbstractCompareAndSwapNode extends FixedAccessNode impleme @Override public Stamp getAccessStamp() { - return expectedValue.stamp().meet(newValue.stamp()).unrestricted(); + return expectedValue.stamp(NodeView.DEFAULT).meet(newValue.stamp(NodeView.DEFAULT)).unrestricted(); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java index fd1409e2184..0ad6b6b4ad3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.meta.MetaAccessProvider; @@ -59,7 +60,7 @@ public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Can protected DynamicNewInstanceNode(NodeClass c, ValueNode clazz, boolean fillContents, FrameState stateBefore) { super(c, StampFactory.objectNonNull(), fillContents, stateBefore); this.clazz = clazz; - assert ((ObjectStamp) clazz.stamp()).nonNull(); + assert ((ObjectStamp) clazz.stamp(NodeView.DEFAULT)).nonNull(); } public ValueNode getInstanceType() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java index d97d138f211..c00e7e842f5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.BeginStateSplitNode; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.KillingBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -79,7 +80,7 @@ public final class ExceptionObjectNode extends BeginStateSplitNode implements Lo */ LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) predecessor()).getLocationIdentity(); AbstractBeginNode entry = graph().add(KillingBeginNode.create(locationsKilledByInvoke)); - LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp())); + LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp(NodeView.DEFAULT))); loadException.setStateAfter(stateAfter()); replaceAtUsages(InputType.Value, loadException); @@ -93,7 +94,7 @@ public final class ExceptionObjectNode extends BeginStateSplitNode implements Lo @Override public boolean verify() { assertTrue(stateAfter() != null, "an exception handler needs a frame state"); - assertTrue(stateAfter().stackSize() == 1 && stateAfter().stackAt(0).stamp().getStackKind() == JavaKind.Object, + assertTrue(stateAfter().stackSize() == 1 && stateAfter().stackAt(0).stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Object, "an exception handler's frame state must have only the exception on the stack"); return super.verify(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java index e63cffefe88..1aac395df8a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.UnaryOpLogicNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IsNullNode; @@ -92,7 +93,7 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu } public static LogicNode createHelper(ObjectStamp checkedStamp, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) { - LogicNode synonym = findSynonym(checkedStamp, object); + LogicNode synonym = findSynonym(checkedStamp, object, NodeView.DEFAULT); if (synonym != null) { return synonym; } else { @@ -107,7 +108,8 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - LogicNode synonym = findSynonym(checkedStamp, forValue); + NodeView view = NodeView.from(tool); + LogicNode synonym = findSynonym(checkedStamp, forValue, view); if (synonym != null) { return synonym; } else { @@ -115,8 +117,8 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu } } - public static LogicNode findSynonym(ObjectStamp checkedStamp, ValueNode object) { - ObjectStamp inputStamp = (ObjectStamp) object.stamp(); + public static LogicNode findSynonym(ObjectStamp checkedStamp, ValueNode object, NodeView view) { + ObjectStamp inputStamp = (ObjectStamp) object.stamp(view); ObjectStamp joinedStamp = (ObjectStamp) checkedStamp.join(inputStamp); if (joinedStamp.isEmpty()) { @@ -158,7 +160,7 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu @Override public void virtualize(VirtualizerTool tool) { ValueNode alias = tool.getAlias(getValue()); - TriState fold = tryFold(alias.stamp()); + TriState fold = tryFold(alias.stamp(NodeView.DEFAULT)); if (fold != TriState.UNKNOWN) { tool.replaceWithValue(LogicConstantNode.forBoolean(fold.isTrue(), graph())); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java index 5ff55d2a65f..56f1ea939e0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; @@ -98,7 +99,8 @@ public final class LoadFieldNode extends AccessFieldNode implements Canonicaliza @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) { - if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile() && (isStatic() || StampTool.isPointerNonNull(forObject.stamp()))) { + NodeView view = NodeView.from(tool); + if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile() && (isStatic() || StampTool.isPointerNonNull(forObject.stamp(view)))) { return null; } return canonical(this, StampPair.create(stamp, uncheckedStamp), forObject, field, tool.getConstantFieldProvider(), @@ -178,10 +180,10 @@ public final class LoadFieldNode extends AccessFieldNode implements Canonicaliza int fieldIndex = ((VirtualInstanceNode) alias).fieldIndex(field()); if (fieldIndex != -1) { ValueNode entry = tool.getEntry((VirtualObjectNode) alias, fieldIndex); - if (stamp.isCompatible(entry.stamp())) { + if (stamp.isCompatible(entry.stamp(NodeView.DEFAULT))) { tool.replaceWith(entry); } else { - assert stamp().getStackKind() == JavaKind.Int && (entry.stamp().getStackKind() == JavaKind.Long || entry.getStackKind() == JavaKind.Double || + assert stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Int && (entry.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Long || entry.getStackKind() == JavaKind.Double || entry.getStackKind() == JavaKind.Illegal) : "Can only allow different stack kind two slot marker writes on one stot fields."; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java index dc2a857c5fa..cb731818fae 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; @@ -92,7 +93,7 @@ public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable, private static JavaKind determinePreciseArrayElementType(ValueNode array, JavaKind kind) { if (kind == JavaKind.Byte) { - ResolvedJavaType javaType = ((ObjectStamp) array.stamp()).type(); + ResolvedJavaType javaType = ((ObjectStamp) array.stamp(NodeView.DEFAULT)).type(); if (javaType != null && javaType.isArray() && javaType.getComponentType() != null && javaType.getComponentType().getJavaKind() == JavaKind.Boolean) { return JavaKind.Boolean; } @@ -114,10 +115,10 @@ public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable, int idx = indexValue.isConstant() ? indexValue.asJavaConstant().asInt() : -1; if (idx >= 0 && idx < virtual.entryCount()) { ValueNode entry = tool.getEntry(virtual, idx); - if (stamp.isCompatible(entry.stamp())) { + if (stamp.isCompatible(entry.stamp(NodeView.DEFAULT))) { tool.replaceWith(entry); } else { - assert stamp().getStackKind() == JavaKind.Int && (entry.stamp().getStackKind() == JavaKind.Long || entry.getStackKind() == JavaKind.Double || + assert stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Int && (entry.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Long || entry.getStackKind() == JavaKind.Double || entry.getStackKind() == JavaKind.Illegal) : "Can only allow different stack kind two slot marker writes on one stot fields."; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java index 46e49c5f606..8cc692a0d7d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -58,11 +59,11 @@ public final class LogicCompareAndSwapNode extends AbstractCompareAndSwapNode { @Override public void generate(NodeLIRBuilderTool gen) { - assert getNewValue().stamp().isCompatible(getExpectedValue().stamp()); + assert getNewValue().stamp(NodeView.DEFAULT).isCompatible(getExpectedValue().stamp(NodeView.DEFAULT)); assert !this.canDeoptimize(); LIRGeneratorTool tool = gen.getLIRGeneratorTool(); - LIRKind resultKind = tool.getLIRKind(stamp()); + LIRKind resultKind = tool.getLIRKind(stamp(NodeView.DEFAULT)); Value trueResult = tool.emitConstant(resultKind, JavaConstant.TRUE); Value falseResult = tool.emitConstant(resultKind, JavaConstant.FALSE); Value result = tool.emitLogicCompareAndSwap(gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()), trueResult, falseResult); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java index dfd3c83419c..f477655786b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; @@ -55,7 +56,7 @@ public final class LoweredAtomicReadAndWriteNode extends FixedAccessNode impleme @OptionalInput(State) FrameState stateAfter; public LoweredAtomicReadAndWriteNode(AddressNode address, LocationIdentity location, ValueNode newValue, BarrierType barrierType) { - super(TYPE, address, location, newValue.stamp().unrestricted(), barrierType); + super(TYPE, address, location, newValue.stamp(NodeView.DEFAULT).unrestricted(), barrierType); this.newValue = newValue; } @@ -93,6 +94,6 @@ public final class LoweredAtomicReadAndWriteNode extends FixedAccessNode impleme @Override public Stamp getAccessStamp() { - return stamp(); + return stamp(NodeView.DEFAULT); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java index c1e3ce64825..105f433f859 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -132,7 +133,7 @@ public class MethodCallTargetNode extends CallTargetNode implements IterableNode return targetMethod; } - return devirtualizeCall(invokeKind, targetMethod, contextType, receiver.graph().getAssumptions(), receiver.stamp()); + return devirtualizeCall(invokeKind, targetMethod, contextType, receiver.graph().getAssumptions(), receiver.stamp(NodeView.DEFAULT)); } public static ResolvedJavaMethod devirtualizeCall(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ResolvedJavaType contextType, Assumptions assumptions, Stamp receiverStamp) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java index a62e08e333d..89fd3ddda60 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.spi.VirtualizableAllocation; @@ -119,7 +120,8 @@ public class NewArrayNode extends AbstractNewArrayNode implements VirtualizableA @Override public void simplify(SimplifierTool tool) { if (hasNoUsages()) { - Stamp lengthStamp = length().stamp(); + NodeView view = NodeView.from(tool); + Stamp lengthStamp = length().stamp(view); if (lengthStamp instanceof IntegerStamp) { IntegerStamp lengthIntegerStamp = (IntegerStamp) lengthStamp; if (lengthIntegerStamp.isPositive()) { @@ -130,7 +132,7 @@ public class NewArrayNode extends AbstractNewArrayNode implements VirtualizableA // Should be areFrameStatesAtSideEffects but currently SVM will complain about // RuntimeConstraint if (graph().getGuardsStage().allowsFloatingGuards()) { - LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), Condition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection()); + LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), Condition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view); // we do not have a non-deopting path for that at the moment so action=None. FixedGuardNode guard = graph().add(new FixedGuardNode(lengthNegativeCondition, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.None, true)); graph().replaceFixedWithFixed(this, guard); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java index 59d3d000ff8..9870bbb9994 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.MonitorEnter; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; @@ -56,7 +57,7 @@ public final class RawMonitorEnterNode extends AccessMonitorNode implements Virt public RawMonitorEnterNode(ValueNode object, ValueNode hub, MonitorIdNode monitorId) { super(TYPE, object, monitorId); - assert ((ObjectStamp) object.stamp()).nonNull(); + assert ((ObjectStamp) object.stamp(NodeView.DEFAULT)).nonNull(); this.hub = hub; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RegisterFinalizerNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RegisterFinalizerNode.java index c1d2d996ac5..7898cc85688 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RegisterFinalizerNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RegisterFinalizerNode.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractStateSplit; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -87,7 +88,7 @@ public final class RegisterFinalizerNode extends AbstractStateSplit implements C * that must be registered with the runtime upon object initialization. */ public static boolean mayHaveFinalizer(ValueNode object, Assumptions assumptions) { - ObjectStamp objectStamp = (ObjectStamp) object.stamp(); + ObjectStamp objectStamp = (ObjectStamp) object.stamp(NodeView.DEFAULT); if (objectStamp.isExactType()) { return objectStamp.type().hasFinalizer(); } else if (objectStamp.type() != null) { @@ -102,7 +103,8 @@ public final class RegisterFinalizerNode extends AbstractStateSplit implements C @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (!(forValue.stamp() instanceof ObjectStamp)) { + NodeView view = NodeView.from(tool); + if (!(forValue.stamp(view) instanceof ObjectStamp)) { return this; } if (!mayHaveFinalizer(forValue, graph().getAssumptions())) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java index 7bc851ad1e4..36223bde288 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.SwitchNode; @@ -64,7 +65,7 @@ public final class TypeSwitchNode extends SwitchNode implements LIRLowerable, Si assert successors.length <= keys.length + 1; assert keySuccessors.length == keyProbabilities.length; this.keys = keys; - assert value.stamp() instanceof AbstractPointerStamp; + assert value.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp; assert assertKeys(); hubs = new Constant[keys.length]; @@ -123,6 +124,7 @@ public final class TypeSwitchNode extends SwitchNode implements LIRLowerable, Si @Override public void simplify(SimplifierTool tool) { + NodeView view = NodeView.from(tool); if (value() instanceof ConstantNode) { Constant constant = value().asConstant(); @@ -139,8 +141,8 @@ public final class TypeSwitchNode extends SwitchNode implements LIRLowerable, Si } killOtherSuccessors(tool, survivingEdge); } - if (value() instanceof LoadHubNode && ((LoadHubNode) value()).getValue().stamp() instanceof ObjectStamp) { - ObjectStamp objectStamp = (ObjectStamp) ((LoadHubNode) value()).getValue().stamp(); + if (value() instanceof LoadHubNode && ((LoadHubNode) value()).getValue().stamp(view) instanceof ObjectStamp) { + ObjectStamp objectStamp = (ObjectStamp) ((LoadHubNode) value()).getValue().stamp(view); if (objectStamp.type() != null) { int validKeys = 0; for (int i = 0; i < keyCount(); i++) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java index 951201be41f..4bbdb302829 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java @@ -30,6 +30,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; @@ -57,7 +58,7 @@ public final class UnsafeCompareAndSwapNode extends AbstractMemoryCheckpoint imp public UnsafeCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, JavaKind valueKind, LocationIdentity locationIdentity) { super(TYPE, StampFactory.forKind(JavaKind.Boolean.getStackKind())); - assert expected.stamp().isCompatible(newValue.stamp()); + assert expected.stamp(NodeView.DEFAULT).isCompatible(newValue.stamp(NodeView.DEFAULT)); this.object = object; this.offset = offset; this.expected = expected; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java index 8f8b9536b5b..5125954d93c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java @@ -28,6 +28,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -46,12 +47,12 @@ public final class ValueCompareAndSwapNode extends AbstractCompareAndSwapNode { } public ValueCompareAndSwapNode(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, BarrierType barrierType) { - super(TYPE, address, location, expectedValue, newValue, barrierType, expectedValue.stamp().meet(newValue.stamp()).unrestricted()); + super(TYPE, address, location, expectedValue, newValue, barrierType, expectedValue.stamp(NodeView.DEFAULT).meet(newValue.stamp(NodeView.DEFAULT)).unrestricted()); } @Override public void generate(NodeLIRBuilderTool gen) { - assert getNewValue().stamp().isCompatible(getExpectedValue().stamp()); + assert getNewValue().stamp(NodeView.DEFAULT).isCompatible(getExpectedValue().stamp(NodeView.DEFAULT)); LIRGeneratorTool tool = gen.getLIRGeneratorTool(); assert !this.canDeoptimize(); gen.setResult(this, tool.emitValueCompareAndSwap(gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()))); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java index c7aac9dcc52..f277b0ad1f0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java @@ -30,6 +30,8 @@ public interface Access extends GuardedNode, HeapAccess { AddressNode getAddress(); + void setAddress(AddressNode address); + LocationIdentity getLocationIdentity(); boolean canNullCheck(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java index 06b3a7f5d2c..9df482b446b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java @@ -54,6 +54,7 @@ public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode impl return address; } + @Override public void setAddress(AddressNode address) { updateUsages(this.address, address); this.address = address; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java index 894b6f62691..43dd02ca8d3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java @@ -58,6 +58,12 @@ public abstract class FloatingAccessNode extends FloatingGuardedNode implements return address; } + @Override + public void setAddress(AddressNode address) { + updateUsages(this.address, address); + this.address = address; + } + @Override public LocationIdentity getLocationIdentity() { return location; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java index 4d2705da114..40dc67fd9a6 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNodeUtil; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.extended.GuardingNode; @@ -65,8 +66,8 @@ public final class FloatingReadNode extends FloatingAccessNode implements LIRLow this.lastLocationAccess = lastLocationAccess; // The input to floating reads must be always non-null or have at least a guard. - assert guard != null || !(address.getBase().stamp() instanceof ObjectStamp) || address.getBase() instanceof ValuePhiNode || - ((ObjectStamp) address.getBase().stamp()).nonNull() : address.getBase(); + assert guard != null || !(address.getBase().stamp(NodeView.DEFAULT) instanceof ObjectStamp) || address.getBase() instanceof ValuePhiNode || + ((ObjectStamp) address.getBase().stamp(NodeView.DEFAULT)).nonNull() : address.getBase(); } @Override @@ -82,7 +83,7 @@ public final class FloatingReadNode extends FloatingAccessNode implements LIRLow @Override public void generate(NodeLIRBuilderTool gen) { - LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp()); + LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitLoad(readKind, gen.operand(address), null)); } @@ -106,7 +107,7 @@ public final class FloatingReadNode extends FloatingAccessNode implements LIRLow @Override public FixedAccessNode asFixedNode() { try (DebugCloseable position = withNodeSourcePosition()) { - ReadNode result = graph().add(new ReadNode(getAddress(), getLocationIdentity(), stamp(), getBarrierType())); + ReadNode result = graph().add(new ReadNode(getAddress(), getLocationIdentity(), stamp(NodeView.DEFAULT), getBarrierType())); result.setGuard(getGuard()); return result; } @@ -121,6 +122,6 @@ public final class FloatingReadNode extends FloatingAccessNode implements LIRLow @Override public Stamp getAccessStamp() { - return stamp(); + return stamp(NodeView.DEFAULT); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java index aac2c80c812..fbe26e2653f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CanonicalizableLocation; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; @@ -94,7 +95,7 @@ public class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, @Override public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) { try (DebugCloseable position = withNodeSourcePosition()) { - return graph().unique(new FloatingReadNode(getAddress(), getLocationIdentity(), lastLocationAccess, stamp(), getGuard(), getBarrierType())); + return graph().unique(new FloatingReadNode(getAddress(), getLocationIdentity(), lastLocationAccess, stamp(NodeView.DEFAULT), getGuard(), getBarrierType())); } } @@ -104,6 +105,7 @@ public class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, } public static ValueNode canonicalizeRead(ValueNode read, AddressNode address, LocationIdentity locationIdentity, CanonicalizerTool tool) { + NodeView view = NodeView.from(tool); MetaAccessProvider metaAccess = tool.getMetaAccess(); if (tool.canonicalizeReads() && address instanceof OffsetAddressNode) { OffsetAddressNode objAddress = (OffsetAddressNode) address; @@ -112,10 +114,10 @@ public class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, long displacement = objAddress.getOffset().asJavaConstant().asLong(); int stableDimension = ((ConstantNode) object).getStableDimension(); if (locationIdentity.isImmutable() || stableDimension > 0) { - Constant constant = read.stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), object.asConstant(), displacement); + Constant constant = read.stamp(view).readConstant(tool.getConstantReflection().getMemoryAccessProvider(), object.asConstant(), displacement); boolean isDefaultStable = locationIdentity.isImmutable() || ((ConstantNode) object).isDefaultStable(); if (constant != null && (isDefaultStable || !constant.isDefaultForKind())) { - return ConstantNode.forConstant(read.stamp(), constant, Math.max(stableDimension - 1, 0), isDefaultStable, metaAccess); + return ConstantNode.forConstant(read.stamp(view), constant, Math.max(stableDimension - 1, 0), isDefaultStable, metaAccess); } } } @@ -128,7 +130,7 @@ public class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, if (locationIdentity instanceof CanonicalizableLocation) { CanonicalizableLocation canonicalize = (CanonicalizableLocation) locationIdentity; ValueNode result = canonicalize.canonicalizeRead(read, address, object, tool); - assert result != null && result.stamp().isCompatible(read.stamp()); + assert result != null && result.stamp(view).isCompatible(read.stamp(view)); return result; } @@ -148,6 +150,6 @@ public class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, @Override public Stamp getAccessStamp() { - return stamp(); + return stamp(NodeView.DEFAULT); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java index bcce27b1a65..a2ecb533fd8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -52,7 +53,7 @@ public class WriteNode extends AbstractWriteNode implements LIRLowerableAccess, @Override public void generate(NodeLIRBuilderTool gen) { - LIRKind writeKind = gen.getLIRGeneratorTool().getLIRKind(value().stamp()); + LIRKind writeKind = gen.getLIRGeneratorTool().getLIRKind(value().stamp(NodeView.DEFAULT)); gen.getLIRGeneratorTool().getArithmetic().emitStore(writeKind, gen.operand(address), gen.operand(value()), gen.state(this)); } @@ -63,7 +64,7 @@ public class WriteNode extends AbstractWriteNode implements LIRLowerableAccess, @Override public Stamp getAccessStamp() { - return value().stamp(); + return value().stamp(NodeView.DEFAULT); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/OffsetAddressNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/OffsetAddressNode.java index 345bef6cd99..2c73ce4537e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/OffsetAddressNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/OffsetAddressNode.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.nodes.memory.address; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.PrimitiveStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -31,6 +32,8 @@ import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; @@ -54,8 +57,12 @@ public class OffsetAddressNode extends AddressNode implements Canonicalizable { this.base = base; this.offset = offset; - assert base != null && (base.stamp() instanceof AbstractPointerStamp || IntegerStamp.getBits(base.stamp()) == 64) && - offset != null && IntegerStamp.getBits(offset.stamp()) == 64 : "both values must have 64 bits"; + assert base != null && (base.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp || IntegerStamp.getBits(base.stamp(NodeView.DEFAULT)) == 64) && + offset != null && IntegerStamp.getBits(offset.stamp(NodeView.DEFAULT)) == 64 : "both values must have 64 bits"; + } + + public static OffsetAddressNode create(ValueNode base) { + return new OffsetAddressNode(base, ConstantNode.forIntegerBits(PrimitiveStamp.getBits(base.stamp(NodeView.DEFAULT)), 0)); } @Override @@ -66,7 +73,7 @@ public class OffsetAddressNode extends AddressNode implements Canonicalizable { public void setBase(ValueNode base) { updateUsages(this.base, base); this.base = base; - assert base != null && (base.stamp() instanceof AbstractPointerStamp || IntegerStamp.getBits(base.stamp()) == 64); + assert base != null && (base.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp || IntegerStamp.getBits(base.stamp(NodeView.DEFAULT)) == 64); } public ValueNode getOffset() { @@ -76,18 +83,16 @@ public class OffsetAddressNode extends AddressNode implements Canonicalizable { public void setOffset(ValueNode offset) { updateUsages(this.offset, offset); this.offset = offset; - assert offset != null && IntegerStamp.getBits(offset.stamp()) == 64; + assert offset != null && IntegerStamp.getBits(offset.stamp(NodeView.DEFAULT)) == 64; } @Override public Node canonical(CanonicalizerTool tool) { - if (base instanceof RawAddressNode) { - // The RawAddressNode is redundant, just directly use its input as base. - return new OffsetAddressNode(((RawAddressNode) base).getAddress(), offset); - } else if (base instanceof OffsetAddressNode) { + if (base instanceof OffsetAddressNode) { + NodeView view = NodeView.from(tool); // Rewrite (&base[offset1])[offset2] to base[offset1 + offset2]. OffsetAddressNode b = (OffsetAddressNode) base; - return new OffsetAddressNode(b.getBase(), BinaryArithmeticNode.add(b.getOffset(), this.getOffset())); + return new OffsetAddressNode(b.getBase(), BinaryArithmeticNode.add(b.getOffset(), this.getOffset(), view)); } else if (base instanceof AddNode) { AddNode add = (AddNode) base; if (add.getY().isConstant()) { @@ -102,7 +107,7 @@ public class OffsetAddressNode extends AddressNode implements Canonicalizable { @Override public long getMaxConstantDisplacement() { - Stamp curStamp = offset.stamp(); + Stamp curStamp = offset.stamp(NodeView.DEFAULT); if (curStamp instanceof IntegerStamp) { IntegerStamp integerStamp = (IntegerStamp) curStamp; if (integerStamp.lowerBound() >= 0) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/RawAddressNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/RawAddressNode.java deleted file mode 100644 index 3a68bf45e04..00000000000 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/RawAddressNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2015, 2015, 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.graalvm.compiler.nodes.memory.address; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; - -/** - * Convert a word-sized integer to a raw address. - */ -@NodeInfo(allowedUsageTypes = InputType.Association) -public class RawAddressNode extends AddressNode { - public static final NodeClass TYPE = NodeClass.create(RawAddressNode.class); - - @Input ValueNode address; - - public RawAddressNode(ValueNode address) { - super(TYPE); - this.address = address; - } - - public ValueNode getAddress() { - return address; - } - - public void setAddress(ValueNode address) { - updateUsages(this.address, address); - this.address = address; - } - - @Override - public ValueNode getBase() { - return address; - } - - @Override - public long getMaxConstantDisplacement() { - return 0; - } - - @Override - public ValueNode getIndex() { - return null; - } -} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/type/StampTool.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/type/StampTool.java index dec36504dde..027b21f3c99 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/type/StampTool.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/type/StampTool.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.code.CodeUtil; @@ -61,9 +62,9 @@ public class StampTool { ValueNode nextValue = iterator.next(); if (nextValue != selfValue) { if (stamp == null) { - stamp = nextValue.stamp(); + stamp = nextValue.stamp(NodeView.DEFAULT); } else { - stamp = stamp.meet(nextValue.stamp()); + stamp = stamp.meet(nextValue.stamp(NodeView.DEFAULT)); } } } @@ -132,7 +133,7 @@ public class StampTool { * @return true if this node represents a legal object value which is known to be always null */ public static boolean isPointerAlwaysNull(ValueNode node) { - return isPointerAlwaysNull(node.stamp()); + return isPointerAlwaysNull(node.stamp(NodeView.DEFAULT)); } /** @@ -158,7 +159,7 @@ public class StampTool { * @return true if this node represents a legal object value which is known to never be null */ public static boolean isPointerNonNull(ValueNode node) { - return isPointerNonNull(node.stamp()); + return isPointerNonNull(node.stamp(NodeView.DEFAULT)); } /** @@ -184,11 +185,11 @@ public class StampTool { * @return the Java type this value has if it is a legal Object type, null otherwise */ public static TypeReference typeReferenceOrNull(ValueNode node) { - return typeReferenceOrNull(node.stamp()); + return typeReferenceOrNull(node.stamp(NodeView.DEFAULT)); } public static ResolvedJavaType typeOrNull(ValueNode node) { - return typeOrNull(node.stamp()); + return typeOrNull(node.stamp(NodeView.DEFAULT)); } public static ResolvedJavaType typeOrNull(Stamp stamp) { @@ -210,7 +211,7 @@ public class StampTool { } public static ResolvedJavaType typeOrNull(ValueNode node, MetaAccessProvider metaAccess) { - return typeOrNull(node.stamp(), metaAccess); + return typeOrNull(node.stamp(NodeView.DEFAULT), metaAccess); } /** @@ -242,7 +243,7 @@ public class StampTool { * @return true if this node represents a legal object value whose Java type is known exactly */ public static boolean isExactType(ValueNode node) { - return isExactType(node.stamp()); + return isExactType(node.stamp(NodeView.DEFAULT)); } /** diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java index 4990cc79e70..fcb46500de5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java @@ -55,6 +55,7 @@ import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ProxyNode; @@ -652,7 +653,7 @@ public class GraphUtil { ValueNode n = node; while (n instanceof PiNode) { PiNode piNode = (PiNode) n; - ObjectStamp originalStamp = (ObjectStamp) piNode.getOriginalNode().stamp(); + ObjectStamp originalStamp = (ObjectStamp) piNode.getOriginalNode().stamp(NodeView.DEFAULT); if (originalStamp.nonNull()) { n = piNode.getOriginalNode(); } else { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java index 0e6839c3120..222dd1d7ed4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java @@ -44,6 +44,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.AbstractNewObjectNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; @@ -111,7 +112,7 @@ public final class CommitAllocationNode extends FixedWithNextNode implements Vir public void lower(LoweringTool tool) { for (int i = 0; i < virtualObjects.size(); i++) { if (ensureVirtual.get(i)) { - EnsureVirtualizedNode.ensureVirtualFailure(this, virtualObjects.get(i).stamp()); + EnsureVirtualizedNode.ensureVirtualFailure(this, virtualObjects.get(i).stamp(NodeView.DEFAULT)); } } tool.getLowerer().lower(this, tool); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/EnsureVirtualizedNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/EnsureVirtualizedNode.java index a24ccf926fd..13ec603f708 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/EnsureVirtualizedNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/EnsureVirtualizedNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.nodes.AbstractEndNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -76,7 +77,7 @@ public final class EnsureVirtualizedNode extends FixedWithNextNode implements Vi @Override public void lower(LoweringTool tool) { - ensureVirtualFailure(this, object.stamp()); + ensureVirtualFailure(this, object.stamp(NodeView.DEFAULT)); } public static void ensureVirtualFailure(Node location, Stamp stamp) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java index c6e8632e5e7..6c7f3c8ce15 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java @@ -23,10 +23,10 @@ */ package org.graalvm.compiler.phases.common; -import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PrefetchAllocateNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -36,10 +36,11 @@ import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; -import org.graalvm.compiler.nodes.memory.address.RawAddressNode; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.Phase; +import jdk.vm.ci.meta.JavaKind; + /** * Created by adinn on 09/05/17. */ @@ -66,22 +67,22 @@ public class AddressLoweringByUsePhase extends Phase { AddressNode lowered; if (node instanceof ReadNode) { ReadNode readNode = (ReadNode) node; - Stamp stamp = readNode.stamp(); + Stamp stamp = readNode.stamp(NodeView.DEFAULT); address = readNode.getAddress(); lowered = lowering.lower(readNode, stamp, address); } else if (node instanceof JavaReadNode) { JavaReadNode javaReadNode = (JavaReadNode) node; - Stamp stamp = javaReadNode.stamp(); + Stamp stamp = javaReadNode.stamp(NodeView.DEFAULT); address = javaReadNode.getAddress(); lowered = lowering.lower(javaReadNode, stamp, address); } else if (node instanceof FloatingReadNode) { FloatingReadNode floatingReadNode = (FloatingReadNode) node; - Stamp stamp = floatingReadNode.stamp(); + Stamp stamp = floatingReadNode.stamp(NodeView.DEFAULT); address = floatingReadNode.getAddress(); lowered = lowering.lower(floatingReadNode, stamp, address); } else if (node instanceof AbstractWriteNode) { AbstractWriteNode abstractWriteNode = (AbstractWriteNode) node; - Stamp stamp = abstractWriteNode.value().stamp(); + Stamp stamp = abstractWriteNode.value().stamp(NodeView.DEFAULT); address = abstractWriteNode.getAddress(); lowered = lowering.lower(abstractWriteNode, stamp, address); } else if (node instanceof PrefetchAllocateNode) { @@ -108,7 +109,7 @@ public class AddressLoweringByUsePhase extends Phase { // now replace any remaining unlowered address nodes for (Node node : graph.getNodes()) { AddressNode lowered; - if (node instanceof RawAddressNode || node instanceof OffsetAddressNode) { + if (node instanceof OffsetAddressNode) { AddressNode address = (AddressNode) node; lowered = lowering.lower(address); } else { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java index dbdada7b0ce..333fbccb610 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java @@ -27,16 +27,12 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; -import org.graalvm.compiler.nodes.memory.address.RawAddressNode; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.Phase; public class AddressLoweringPhase extends Phase { public abstract static class AddressLowering { - - public abstract AddressNode lower(ValueNode address); - public abstract AddressNode lower(ValueNode base, ValueNode offset); } @@ -51,10 +47,7 @@ public class AddressLoweringPhase extends Phase { protected void run(StructuredGraph graph) { for (Node node : graph.getNodes()) { AddressNode lowered; - if (node instanceof RawAddressNode) { - RawAddressNode address = (RawAddressNode) node; - lowered = lowering.lower(address.getAddress()); - } else if (node instanceof OffsetAddressNode) { + if (node instanceof OffsetAddressNode) { OffsetAddressNode address = (OffsetAddressNode) node; lowered = lowering.lower(address.getBase(), address.getOffset()); } else { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java index 232fd32c383..957984e2242 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.phases.common; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; @@ -44,6 +45,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -153,6 +155,10 @@ public class CanonicalizerPhase extends BasePhase { new Instance(context, workingSet, newNodesMark).apply(graph, dumpGraph); } + public NodeView getNodeView() { + return NodeView.DEFAULT; + } + private final class Instance extends Phase { private final Mark newNodesMark; @@ -260,9 +266,9 @@ public class CanonicalizerPhase extends BasePhase { if (node instanceof ValueNode) { ValueNode valueNode = (ValueNode) node; boolean improvedStamp = tryInferStamp(valueNode); - Constant constant = valueNode.stamp().asConstant(); + Constant constant = valueNode.stamp(NodeView.DEFAULT).asConstant(); if (constant != null && !(node instanceof ConstantNode)) { - ConstantNode stampConstant = ConstantNode.forConstant(valueNode.stamp(), constant, context.getMetaAccess(), graph); + ConstantNode stampConstant = ConstantNode.forConstant(valueNode.stamp(NodeView.DEFAULT), constant, context.getMetaAccess(), graph); debug.log("Canonicalizer: constant stamp replaces %1s with %1s", valueNode, stampConstant); valueNode.replaceAtUsages(InputType.Value, stampConstant); GraphUtil.tryKillUnused(valueNode); @@ -442,14 +448,16 @@ public class CanonicalizerPhase extends BasePhase { return false; } - private final class Tool implements SimplifierTool { + private final class Tool implements SimplifierTool, NodeView { private final Assumptions assumptions; private final OptionValues options; + private NodeView nodeView; Tool(Assumptions assumptions, OptionValues options) { this.assumptions = assumptions; this.options = options; + this.nodeView = getNodeView(); } @Override @@ -513,6 +521,11 @@ public class CanonicalizerPhase extends BasePhase { public OptionValues getOptions() { return options; } + + @Override + public Stamp stamp(ValueNode node) { + return nodeView.stamp(node); + } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java index 3530b938204..0f1c4206191 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java @@ -58,6 +58,7 @@ import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ProxyNode; @@ -414,7 +415,7 @@ public class ConditionalEliminationPhase extends BasePhase { Stamp bestPossibleStamp = null; for (int i = 0; i < phi.valueCount(); ++i) { ValueNode valueAt = phi.valueAt(i); - Stamp curBestStamp = valueAt.stamp(); + Stamp curBestStamp = valueAt.stamp(NodeView.DEFAULT); InfoElement infoElement = phiInfoElements.get(merge.forwardEndAt(i)); if (infoElement != null) { curBestStamp = curBestStamp.join(infoElement.getStamp()); @@ -427,7 +428,7 @@ public class ConditionalEliminationPhase extends BasePhase { } } - Stamp oldStamp = phi.stamp(); + Stamp oldStamp = phi.stamp(NodeView.DEFAULT); if (oldStamp.tryImproveWith(bestPossibleStamp) != null) { // Need to be careful to not run into stamp update cycles with the iterative @@ -460,7 +461,7 @@ public class ConditionalEliminationPhase extends BasePhase { ValuePhiNode newPhi = graph.addWithoutUnique(new ValuePhiNode(bestPossibleStamp, merge)); for (int i = 0; i < phi.valueCount(); ++i) { ValueNode valueAt = phi.valueAt(i); - if (bestPossibleStamp.meet(valueAt.stamp()).equals(bestPossibleStamp)) { + if (bestPossibleStamp.meet(valueAt.stamp(NodeView.DEFAULT)).equals(bestPossibleStamp)) { // Pi not required here. } else { InfoElement infoElement = phiInfoElements.get(merge.forwardEndAt(i)); @@ -494,7 +495,7 @@ public class ConditionalEliminationPhase extends BasePhase { InfoElement infoElement = this.getInfoElements(valueAt); while (infoElement != null) { Stamp newStamp = infoElement.getStamp(); - if (phi.stamp().tryImproveWith(newStamp) != null) { + if (phi.stamp(NodeView.DEFAULT).tryImproveWith(newStamp) != null) { if (mergeMap == null) { mergeMap = EconomicMap.create(); mergeMaps.put(merge, mergeMap); @@ -547,7 +548,7 @@ public class ConditionalEliminationPhase extends BasePhase { * It's equivalent to or'ing in the mask value since those values are * known to be set. */ - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getOr(); + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(NodeView.DEFAULT)).getOr(); IntegerStamp newStampX = (IntegerStamp) op.foldStamp(getSafeStamp(andX), getOtherSafeStamp(y)); registerNewStamp(andX, newStampX, guard); } @@ -580,7 +581,7 @@ public class ConditionalEliminationPhase extends BasePhase { if (y.isConstant()) { InfoElement infoElement = getInfoElements(x); while (infoElement != null) { - Stamp result = binary.foldStamp(infoElement.stamp, y.stamp()); + Stamp result = binary.foldStamp(infoElement.stamp, y.stamp(NodeView.DEFAULT)); if (result != null) { return Pair.create(infoElement, result); } @@ -597,7 +598,7 @@ public class ConditionalEliminationPhase extends BasePhase { * registered info elements is in the same chain of pi nodes. */ private static Stamp getSafeStamp(ValueNode x) { - return x.stamp(); + return x.stamp(NodeView.DEFAULT); } /** @@ -610,9 +611,9 @@ public class ConditionalEliminationPhase extends BasePhase { */ private static Stamp getOtherSafeStamp(ValueNode x) { if (x.isConstant()) { - return x.stamp(); + return x.stamp(NodeView.DEFAULT); } - return x.stamp().unrestricted(); + return x.stamp(NodeView.DEFAULT).unrestricted(); } /** @@ -777,7 +778,7 @@ public class ConditionalEliminationPhase extends BasePhase { ValueNode y = binaryOpLogicNode.getY(); infoElement = getInfoElements(x); while (infoElement != null) { - TriState result = binaryOpLogicNode.tryFold(infoElement.getStamp(), y.stamp()); + TriState result = binaryOpLogicNode.tryFold(infoElement.getStamp(), y.stamp(NodeView.DEFAULT)); if (result.isKnown()) { return rewireGuards(infoElement.getGuard(), result.toBoolean(), infoElement.getProxifiedInput(), infoElement.getStamp(), rewireGuardFunction); } @@ -787,7 +788,7 @@ public class ConditionalEliminationPhase extends BasePhase { if (y.isConstant()) { Pair foldResult = recursiveFoldStampFromInfo(x); if (foldResult != null) { - TriState result = binaryOpLogicNode.tryFold(foldResult.getRight(), y.stamp()); + TriState result = binaryOpLogicNode.tryFold(foldResult.getRight(), y.stamp(NodeView.DEFAULT)); if (result.isKnown()) { return rewireGuards(foldResult.getLeft().getGuard(), result.toBoolean(), foldResult.getLeft().getProxifiedInput(), foldResult.getRight(), rewireGuardFunction); } @@ -795,7 +796,7 @@ public class ConditionalEliminationPhase extends BasePhase { } else { infoElement = getInfoElements(y); while (infoElement != null) { - TriState result = binaryOpLogicNode.tryFold(x.stamp(), infoElement.getStamp()); + TriState result = binaryOpLogicNode.tryFold(x.stamp(NodeView.DEFAULT), infoElement.getStamp()); if (result.isKnown()) { return rewireGuards(infoElement.getGuard(), result.toBoolean(), infoElement.getProxifiedInput(), infoElement.getStamp(), rewireGuardFunction); } @@ -815,8 +816,8 @@ public class ConditionalEliminationPhase extends BasePhase { if (binary.getY().isConstant()) { infoElement = getInfoElements(binary.getX()); while (infoElement != null) { - Stamp newStampX = binary.foldStamp(infoElement.getStamp(), binary.getY().stamp()); - TriState result = binaryOpLogicNode.tryFold(newStampX, y.stamp()); + Stamp newStampX = binary.foldStamp(infoElement.getStamp(), binary.getY().stamp(NodeView.DEFAULT)); + TriState result = binaryOpLogicNode.tryFold(newStampX, y.stamp(NodeView.DEFAULT)); if (result.isKnown()) { return rewireGuards(infoElement.getGuard(), result.toBoolean(), infoElement.getProxifiedInput(), newStampX, rewireGuardFunction); } @@ -834,7 +835,7 @@ public class ConditionalEliminationPhase extends BasePhase { * It's equivalent to or'ing in the mask value since those values are * known to be set. */ - BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getOr(); + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(NodeView.DEFAULT)).getOr(); IntegerStamp newStampX = (IntegerStamp) op.foldStamp(getSafeStamp(and.getX()), getOtherSafeStamp(y)); if (foldPendingTest(thisGuard, and.getX(), newStampX, rewireGuardFunction)) { return true; @@ -899,7 +900,7 @@ public class ConditionalEliminationPhase extends BasePhase { do { counterStampsRegistered.increment(debug); debug.log("\t Saving stamp for node %s stamp %s guarded by %s", value, stamp, guard); - assert value instanceof LogicNode || stamp.isCompatible(value.stamp()) : stamp + " vs. " + value.stamp() + " (" + value + ")"; + assert value instanceof LogicNode || stamp.isCompatible(value.stamp(NodeView.DEFAULT)) : stamp + " vs. " + value.stamp(NodeView.DEFAULT) + " (" + value + ")"; map.setAndGrow(value, new InfoElement(stamp, guard, proxiedValue, map.getAndGrow(value))); undoOperations.push(value); if (value instanceof StampInverter) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java index 81caff4a201..889c11cb67e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ShortCircuitOrNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -68,15 +69,15 @@ public class ExpandLogicPhase extends Phase { StructuredGraph graph = normalize.graph(); ValueNode x = normalize.getX(); ValueNode y = normalize.getY(); - if (x.stamp() instanceof FloatStamp) { - equalComp = graph.addOrUniqueWithInputs(FloatEqualsNode.create(x, y)); - lessComp = graph.addOrUniqueWithInputs(FloatLessThanNode.create(x, y, normalize.isUnorderedLess())); + if (x.stamp(NodeView.DEFAULT) instanceof FloatStamp) { + equalComp = graph.addOrUniqueWithInputs(FloatEqualsNode.create(x, y, NodeView.DEFAULT)); + lessComp = graph.addOrUniqueWithInputs(FloatLessThanNode.create(x, y, normalize.isUnorderedLess(), NodeView.DEFAULT)); } else { - equalComp = graph.addOrUniqueWithInputs(IntegerEqualsNode.create(x, y)); - lessComp = graph.addOrUniqueWithInputs(IntegerLessThanNode.create(x, y)); + equalComp = graph.addOrUniqueWithInputs(IntegerEqualsNode.create(x, y, NodeView.DEFAULT)); + lessComp = graph.addOrUniqueWithInputs(IntegerLessThanNode.create(x, y, NodeView.DEFAULT)); } - Stamp stamp = normalize.stamp(); + Stamp stamp = normalize.stamp(NodeView.DEFAULT); ConditionalNode equalValue = graph.unique( new ConditionalNode(equalComp, ConstantNode.forIntegerStamp(stamp, 0, graph), ConstantNode.forIntegerStamp(stamp, 1, graph))); ConditionalNode value = graph.unique(new ConditionalNode(lessComp, ConstantNode.forIntegerStamp(stamp, -1, graph), equalValue)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java index b1379d9b0ca..0d183bdeb0e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java @@ -42,6 +42,7 @@ import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -115,7 +116,7 @@ public class FixReadsPhase extends BasePhase { replaceCurrent(fixedAccess); } else if (node instanceof PiNode) { PiNode piNode = (PiNode) node; - if (piNode.stamp().isCompatible(piNode.getOriginalNode().stamp())) { + if (piNode.stamp(NodeView.DEFAULT).isCompatible(piNode.getOriginalNode().stamp(NodeView.DEFAULT))) { // Pi nodes are no longer necessary at this point. piNode.replaceAndDelete(piNode.getOriginalNode()); } @@ -178,7 +179,7 @@ public class FixReadsPhase extends BasePhase { } counterConstantInputReplacements.increment(node.getDebug()); ConstantNode stampConstant = ConstantNode.forConstant(bestStamp, constant, metaAccess, graph); - assert stampConstant.stamp().isCompatible(valueNode.stamp()); + assert stampConstant.stamp(NodeView.DEFAULT).isCompatible(valueNode.stamp(NodeView.DEFAULT)); replaceInput(p, node, stampConstant); replacements++; } @@ -258,7 +259,7 @@ public class FixReadsPhase extends BasePhase { bestStamp = bestStamp.meet(currentEndMap.get(phi)); } - if (!bestStamp.equals(phi.stamp())) { + if (!bestStamp.equals(phi.stamp(NodeView.DEFAULT))) { endMap.put(phi, bestStamp); } } @@ -293,7 +294,7 @@ public class FixReadsPhase extends BasePhase { bestStamp = bestStamp.meet(otherEndsStamp); } - if (nodeWithNewStamp.stamp().tryImproveWith(bestStamp) == null) { + if (nodeWithNewStamp.stamp(NodeView.DEFAULT).tryImproveWith(bestStamp) == null) { // No point in registering the stamp. } else { endMap.put(nodeWithNewStamp, bestStamp); @@ -462,7 +463,7 @@ public class FixReadsPhase extends BasePhase { ValueNode originalNode = value; StampElement currentStamp = stampMap.getAndGrow(originalNode); if (currentStamp == null) { - return value.stamp(); + return value.stamp(NodeView.DEFAULT); } return currentStamp.getStamp(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NonNullParametersPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NonNullParametersPhase.java index a25a2b8ad62..e1094687706 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NonNullParametersPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NonNullParametersPhase.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.phases.common; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.Phase; @@ -39,8 +40,8 @@ public class NonNullParametersPhase extends Phase { protected void run(StructuredGraph graph) { Stamp nonNull = StampFactory.objectNonNull(); for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { - if (param.stamp() instanceof ObjectStamp) { - ObjectStamp paramStamp = (ObjectStamp) param.stamp(); + if (param.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { + ObjectStamp paramStamp = (ObjectStamp) param.stamp(NodeView.DEFAULT); param.setStamp(paramStamp.join(nonNull)); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java index c395bcca3fc..1f632ea2faf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java @@ -160,7 +160,7 @@ public class ProfileCompiledMethodsPhase extends Phase { return 10; } else if (node instanceof Access) { return 2; - } else if (node instanceof LogicNode || node instanceof ConvertNode || node instanceof BinaryNode || node instanceof NotNode) { + } else if (node instanceof LogicNode || node instanceof ConvertNode || node instanceof NotNode) { return 1; } else if (node instanceof IntegerDivRemNode || node instanceof FloatDivNode || node instanceof RemNode) { return 10; @@ -168,7 +168,7 @@ public class ProfileCompiledMethodsPhase extends Phase { return 3; } else if (node instanceof Invoke) { return 5; - } else if (node instanceof IfNode || node instanceof SafepointNode) { + } else if (node instanceof IfNode || node instanceof SafepointNode || node instanceof BinaryNode) { return 1; } else if (node instanceof SwitchNode) { return node.successors().count(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java index 2711f097b43..f0db2b4df29 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java @@ -69,6 +69,7 @@ import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.KillingBeginNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; @@ -827,7 +828,7 @@ public class InliningUtil extends ValueMergeUtil { if (newReceiver.getStackKind() == JavaKind.Object) { if (invoke.getInvokeKind() == InvokeKind.Special) { - Stamp paramStamp = newReceiver.stamp(); + Stamp paramStamp = newReceiver.stamp(NodeView.DEFAULT); Stamp stamp = paramStamp.join(StampFactory.object(TypeReference.create(graph.getAssumptions(), callTarget.targetMethod().getDeclaringClass()))); if (!stamp.equals(paramStamp)) { // The verifier and previous optimizations guarantee unconditionally that the diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java index f01aec572b2..c117547930f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -191,7 +192,7 @@ public class MultiTypeGuardInlineInfo extends AbstractInlineInfo { PhiNode returnValuePhi = null; if (invoke.asNode().getStackKind() != JavaKind.Void) { - returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp().unrestricted(), returnMerge)); + returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp(NodeView.DEFAULT).unrestricted(), returnMerge)); } AbstractMergeNode exceptionMerge = null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java index 969458fedbb..1127d5d76fc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; @@ -111,9 +112,9 @@ public class TypeGuardInlineInfo extends AbstractInlineInfo { private void createGuard(StructuredGraph graph, Providers providers) { ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver)); - ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph); + ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(NodeView.DEFAULT), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph); - LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection()); + LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT); FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); assert invoke.predecessor() != null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java index 35d076543a6..317a0556b58 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -120,8 +121,8 @@ public class InlineableGraph implements Inlineable { } private static Stamp improvedStamp(ValueNode arg, ParameterNode param) { - Stamp joinedStamp = param.stamp().join(arg.stamp()); - if (joinedStamp == null || joinedStamp.equals(param.stamp())) { + Stamp joinedStamp = param.stamp(NodeView.DEFAULT).join(arg.stamp(NodeView.DEFAULT)); + if (joinedStamp == null || joinedStamp.equals(param.stamp(NodeView.DEFAULT))) { return null; } return joinedStamp; @@ -162,7 +163,7 @@ public class InlineableGraph implements Inlineable { parameterUsages = trackParameterUsages(param, parameterUsages); // collect param usages before replacing the param param.replaceAtUsagesAndDelete(graph.unique( - ConstantNode.forConstant(arg.stamp(), constant.getValue(), constant.getStableDimension(), constant.isDefaultStable(), context.getMetaAccess()))); + ConstantNode.forConstant(arg.stamp(NodeView.DEFAULT), constant.getValue(), constant.getStableDimension(), constant.isDefaultStable(), context.getMetaAccess()))); // param-node gone, leaving a gap in the sequence given by param.index() } else { Stamp impro = improvedStamp(arg, param); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java index 56475ba11e9..ed6a1208f27 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java @@ -42,6 +42,7 @@ import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -192,10 +193,10 @@ public class InliningData { assert callTarget.invokeKind().isIndirect(); ResolvedJavaType holder = targetMethod.getDeclaringClass(); - if (!(callTarget.receiver().stamp() instanceof ObjectStamp)) { + if (!(callTarget.receiver().stamp(NodeView.DEFAULT) instanceof ObjectStamp)) { return null; } - ObjectStamp receiverStamp = (ObjectStamp) callTarget.receiver().stamp(); + ObjectStamp receiverStamp = (ObjectStamp) callTarget.receiver().stamp(NodeView.DEFAULT); if (receiverStamp.alwaysNull()) { // Don't inline if receiver is known to be null return null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/InferStamps.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/InferStamps.java index 1bd1ad5ea20..85281e1a19c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/InferStamps.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/InferStamps.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.phases.graph; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; @@ -50,9 +51,9 @@ public class InferStamps { for (Node n : graph.getNodes()) { if (n instanceof ValuePhiNode) { ValueNode node = (ValueNode) n; - if (node.stamp() instanceof ObjectStamp) { - assert node.stamp().hasValues() : "We assume all Phi and Proxy stamps are legal before the analysis"; - node.setStamp(node.stamp().empty()); + if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { + assert node.stamp(NodeView.DEFAULT).hasValues() : "We assume all Phi and Proxy stamps are legal before the analysis"; + node.setStamp(node.stamp(NodeView.DEFAULT).empty()); } } } @@ -71,7 +72,7 @@ public class InferStamps { for (Node n : graph.getNodes()) { if (n instanceof ValueNode) { ValueNode node = (ValueNode) n; - if (node.stamp() instanceof ObjectStamp) { + if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { stampChanged |= node.inferStamp(); } } @@ -90,7 +91,8 @@ public class InferStamps { for (Node n : graph.getNodes()) { if (n instanceof ValuePhiNode) { ValueNode node = (ValueNode) n; - assert node.stamp().hasValues() : "Stamp is empty after analysis. This is not necessarily an error, but a condition that we want to investigate (and then maybe relax or remove the assertion)."; + assert node.stamp( + NodeView.DEFAULT).hasValues() : "Stamp is empty after analysis. This is not necessarily an error, but a condition that we want to investigate (and then maybe relax or remove the assertion)."; } } return true; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/ValueMergeUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/ValueMergeUtil.java index 7ed4b1821f9..8b4d18381cd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/ValueMergeUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/ValueMergeUtil.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.UnwindNode; @@ -52,7 +53,7 @@ public class ValueMergeUtil { singleResult = result; } else if (phiResult == null) { /* Found a second result value, so create phi node. */ - phiResult = merge.graph().addWithoutUnique(new ValuePhiNode(result.stamp().unrestricted(), merge)); + phiResult = merge.graph().addWithoutUnique(new ValuePhiNode(result.stamp(NodeView.DEFAULT).unrestricted(), merge)); for (int i = 0; i < merge.forwardEndCount(); i++) { phiResult.addInput(singleResult); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java index c2cefd1cfdf..e195ad1875b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; @@ -234,7 +235,7 @@ public class VerifyDebugUsage extends VerifyPhase { protected void verifyDumpObjectParameter(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, ValueNode arg, ResolvedJavaMethod verifiedCallee, Integer dumpLevel) throws org.graalvm.compiler.phases.VerifyPhase.VerificationError { - ResolvedJavaType argType = ((ObjectStamp) arg.stamp()).type(); + ResolvedJavaType argType = ((ObjectStamp) arg.stamp(NodeView.DEFAULT)).type(); if (metaAccess.lookupJavaType(Graph.class).isAssignableFrom(argType)) { verifyStructuredGraphDumping(callerGraph, debugCallTarget, verifiedCallee, dumpLevel); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyUsageWithEquals.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyUsageWithEquals.java index 30563849c2d..e4e14911d82 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyUsageWithEquals.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyUsageWithEquals.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.phases.verify; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -80,7 +81,7 @@ public class VerifyUsageWithEquals extends VerifyPhase { * Determines whether the type of {@code node} is assignable to the {@link #restrictedClass}. */ private boolean isAssignableToRestrictedType(ValueNode node, MetaAccessProvider metaAccess) { - if (node.stamp() instanceof ObjectStamp) { + if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { ResolvedJavaType restrictedType = metaAccess.lookupJavaType(restrictedClass); ResolvedJavaType nodeType = StampTool.typeOrNull(node); if (nodeType == null && node instanceof LoadFieldNode) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyVirtualizableUsage.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyVirtualizableUsage.java index ace130325ce..1b29868ba06 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyVirtualizableUsage.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyVirtualizableUsage.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; @@ -81,7 +82,7 @@ public class VerifyVirtualizableUsage extends VerifyPhase { int i = 0; for (Node arg : arguments) { if (i >= startIdx) { - Stamp argStamp = ((ValueNode) arg).stamp(); + Stamp argStamp = ((ValueNode) arg).stamp(NodeView.DEFAULT); if (argStamp instanceof ObjectStamp) { ObjectStamp objectStamp = (ObjectStamp) argStamp; ResolvedJavaType argStampType = objectStamp.type(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java index f40d78c6fc5..d5dc2508341 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java @@ -92,7 +92,7 @@ public class BinaryGraphPrinter implements @Override public void beginGroup(DebugContext debug, String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) throws IOException { - output.beginGroup(new GraphInfo(debug, null), name, shortName, method, bci, properties); + output.beginGroup(new GraphInfo(debug, null), name, shortName, method, bci, DebugContext.addVersionProperties(properties)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountLeadingZerosNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountLeadingZerosNode.java index 9d5463b6b37..6568ecc9198 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountLeadingZerosNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountLeadingZerosNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -48,7 +49,7 @@ public final class AArch64CountLeadingZerosNode extends UnaryNode implements Ari public static final NodeClass TYPE = NodeClass.create(AArch64CountLeadingZerosNode.class); public AArch64CountLeadingZerosNode(ValueNode value) { - super(TYPE, computeStamp(value.stamp(), value), value); + super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), value), value); } @Override @@ -57,7 +58,7 @@ public final class AArch64CountLeadingZerosNode extends UnaryNode implements Ari } private static Stamp computeStamp(Stamp newStamp, ValueNode theValue) { - assert newStamp.isCompatible(theValue.stamp()); + assert newStamp.isCompatible(theValue.stamp(NodeView.DEFAULT)); assert theValue.getStackKind() == JavaKind.Int || theValue.getStackKind() == JavaKind.Long; return StampTool.stampForLeadingZeros((IntegerStamp) newStamp); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountTrailingZerosNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountTrailingZerosNode.java index ac7d674b0e1..54e7e653b6f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountTrailingZerosNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64CountTrailingZerosNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -50,7 +51,7 @@ public final class AArch64CountTrailingZerosNode extends UnaryNode implements Ar public static final NodeClass TYPE = NodeClass.create(AArch64CountTrailingZerosNode.class); public AArch64CountTrailingZerosNode(ValueNode value) { - super(TYPE, computeStamp(value.stamp(), value), value); + super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), value), value); assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; } @@ -60,7 +61,7 @@ public final class AArch64CountTrailingZerosNode extends UnaryNode implements Ar } static Stamp computeStamp(Stamp newStamp, ValueNode value) { - assert newStamp.isCompatible(value.stamp()); + assert newStamp.isCompatible(value.stamp(NodeView.DEFAULT)); IntegerStamp valueStamp = (IntegerStamp) newStamp; return StampTool.stampForTrailingZeros(valueStamp); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64FloatArithmeticSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64FloatArithmeticSnippets.java index 339af5d5dc3..ad5dbccd87f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64FloatArithmeticSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64FloatArithmeticSnippets.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.RemNode; @@ -63,7 +64,7 @@ public class AArch64FloatArithmeticSnippets extends SnippetTemplate.AbstractTemp } public void lower(RemNode node, LoweringTool tool) { - JavaKind kind = node.stamp().getStackKind(); + JavaKind kind = node.stamp(NodeView.DEFAULT).getStackKind(); assert kind == JavaKind.Float || kind == JavaKind.Double; if (node instanceof SafeNode) { // We already introduced the necessary checks, nothing to do. diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java index b45c2e4272f..cf6ba186a14 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FixedBinaryNode; @@ -84,7 +85,7 @@ public class AArch64IntegerArithmeticSnippets extends AbstractTemplates implemen } public void lower(FixedBinaryNode node, LoweringTool tool) { - JavaKind kind = node.stamp().getStackKind(); + JavaKind kind = node.stamp(NodeView.DEFAULT).getStackKind(); assert kind == JavaKind.Int || kind == JavaKind.Long; SnippetTemplate.SnippetInfo snippet; if (node instanceof SafeNode) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadNode.java index a9eec477b0c..1baec57dac2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.SignExtendNode; @@ -66,7 +67,7 @@ public class AArch64ReadNode extends ReadNode { AArch64LIRGenerator lirgen = (AArch64LIRGenerator) gen.getLIRGeneratorTool(); AArch64ArithmeticLIRGenerator arithgen = (AArch64ArithmeticLIRGenerator) lirgen.getArithmetic(); AArch64Kind readKind = (AArch64Kind) lirgen.getLIRKind(accessStamp).getPlatformKind(); - int resultBits = ((IntegerStamp) stamp()).getBits(); + int resultBits = ((IntegerStamp) stamp(NodeView.DEFAULT)).getBits(); gen.setResult(this, arithgen.emitExtendMemory(isSigned, readKind, resultBits, (AArch64AddressValue) gen.operand(getAddress()), gen.state(this))); } @@ -86,7 +87,7 @@ public class AArch64ReadNode extends ReadNode { AddressNode address = readNode.getAddress(); LocationIdentity location = readNode.getLocationIdentity(); - Stamp stamp = usage.stamp(); + Stamp stamp = usage.stamp(NodeView.DEFAULT); GuardingNode guard = readNode.getGuard(); BarrierType barrierType = readNode.getBarrierType(); boolean nullCheck = readNode.getNullCheck(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountLeadingZerosNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountLeadingZerosNode.java index 56938d2c930..160ba55bba8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountLeadingZerosNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountLeadingZerosNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -50,7 +51,7 @@ public final class AMD64CountLeadingZerosNode extends UnaryNode implements Arith public static final NodeClass TYPE = NodeClass.create(AMD64CountLeadingZerosNode.class); public AMD64CountLeadingZerosNode(ValueNode value) { - super(TYPE, computeStamp(value.stamp(), value), value); + super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), value), value); assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; } @@ -60,7 +61,7 @@ public final class AMD64CountLeadingZerosNode extends UnaryNode implements Arith } private static Stamp computeStamp(Stamp newStamp, ValueNode theValue) { - assert newStamp.isCompatible(theValue.stamp()); + assert newStamp.isCompatible(theValue.stamp(NodeView.DEFAULT)); assert theValue.getStackKind() == JavaKind.Int || theValue.getStackKind() == JavaKind.Long; return StampTool.stampForLeadingZeros((IntegerStamp) newStamp); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountTrailingZerosNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountTrailingZerosNode.java index 3c17918d5bf..d9314d4948f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountTrailingZerosNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountTrailingZerosNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -50,7 +51,7 @@ public final class AMD64CountTrailingZerosNode extends UnaryNode implements Arit public static final NodeClass TYPE = NodeClass.create(AMD64CountTrailingZerosNode.class); public AMD64CountTrailingZerosNode(ValueNode value) { - super(TYPE, computeStamp(value.stamp(), value), value); + super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), value), value); assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; } @@ -60,7 +61,7 @@ public final class AMD64CountTrailingZerosNode extends UnaryNode implements Arit } static Stamp computeStamp(Stamp newStamp, ValueNode value) { - assert newStamp.isCompatible(value.stamp()); + assert newStamp.isCompatible(value.stamp(NodeView.DEFAULT)); IntegerStamp valueStamp = (IntegerStamp) newStamp; return StampTool.stampForTrailingZeros(valueStamp); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64RoundNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64RoundNode.java index 4a980b0cbb7..54674b55e53 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64RoundNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64RoundNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool.RoundingMo import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -52,7 +53,7 @@ public final class AMD64RoundNode extends UnaryNode implements ArithmeticLIRLowe private final RoundingMode mode; public AMD64RoundNode(ValueNode value, RoundingMode mode) { - super(TYPE, roundStamp((FloatStamp) value.stamp(), mode), value); + super(TYPE, roundStamp((FloatStamp) value.stamp(NodeView.DEFAULT), mode), value); this.mode = mode; } @@ -83,7 +84,7 @@ public final class AMD64RoundNode extends UnaryNode implements ArithmeticLIRLowe @Override public Stamp foldStamp(Stamp newStamp) { - assert newStamp.isCompatible(getValue().stamp()); + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); return roundStamp((FloatStamp) newStamp, mode); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BitOpNodesTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BitOpNodesTest.java index 2dd8252aeb9..2aeda14b2ed 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BitOpNodesTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BitOpNodesTest.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.replacements.test; +import org.graalvm.compiler.nodes.NodeView; import org.junit.Assert; import org.junit.Assume; import org.junit.Test; @@ -83,7 +84,7 @@ public class BitOpNodesTest extends GraalCompilerTest { boolean isSparc = arch instanceof SPARC; Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc); ValueNode result = parseAndInline("bitCountIntSnippet"); - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 8, 24), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 8, 24), result.stamp(NodeView.DEFAULT)); } public static int bitCountIntEmptySnippet(int v) { @@ -97,7 +98,7 @@ public class BitOpNodesTest extends GraalCompilerTest { boolean isSparc = arch instanceof SPARC; Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc); ValueNode result = parseAndInline("bitCountIntEmptySnippet"); - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 0, 24), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 0, 24), result.stamp(NodeView.DEFAULT)); } @Test @@ -117,7 +118,7 @@ public class BitOpNodesTest extends GraalCompilerTest { boolean isSparc = arch instanceof SPARC; Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc); ValueNode result = parseAndInline("bitCountLongSnippet"); - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 8, 40), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 8, 40), result.stamp(NodeView.DEFAULT)); } public static int bitCountLongEmptySnippet(long v) { @@ -131,7 +132,7 @@ public class BitOpNodesTest extends GraalCompilerTest { boolean isSparc = arch instanceof SPARC; Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc); ValueNode result = parseAndInline("bitCountLongEmptySnippet"); - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 0, 40), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 0, 40), result.stamp(NodeView.DEFAULT)); } /* @@ -155,7 +156,7 @@ public class BitOpNodesTest extends GraalCompilerTest { @Test public void testScanForwardInt() { ValueNode result = parseAndInline("scanForwardIntSnippet"); - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 4, 8), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 4, 8), result.stamp(NodeView.DEFAULT)); } public static int scanForwardLongConstantSnippet() { @@ -175,7 +176,7 @@ public class BitOpNodesTest extends GraalCompilerTest { @Test public void testScanForwardLong() { ValueNode result = parseAndInline("scanForwardLongSnippet"); - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 32), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 32), result.stamp(NodeView.DEFAULT)); } public static int scanForwardLongEmptySnippet(long v) { @@ -187,7 +188,7 @@ public class BitOpNodesTest extends GraalCompilerTest { @Test public void testScanForwardLongEmpty() { ValueNode result = parseAndInline("scanForwardLongEmptySnippet"); - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 64), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 64), result.stamp(NodeView.DEFAULT)); } /* @@ -213,7 +214,7 @@ public class BitOpNodesTest extends GraalCompilerTest { /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */ ValueNode result = parseAndInline("scanReverseIntSnippet", BitScanReverseNode.class); if (result != null) { - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 16, 20), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 16, 20), result.stamp(NodeView.DEFAULT)); } } @@ -238,7 +239,7 @@ public class BitOpNodesTest extends GraalCompilerTest { /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */ ValueNode result = parseAndInline("scanReverseLongSnippet", BitScanReverseNode.class); if (result != null) { - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 48, 64), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 48, 64), result.stamp(NodeView.DEFAULT)); } } @@ -253,7 +254,7 @@ public class BitOpNodesTest extends GraalCompilerTest { /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */ ValueNode result = parseAndInline("scanReverseLongEmptySnippet", BitScanReverseNode.class); if (result != null) { - Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 64), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 64), result.stamp(NodeView.DEFAULT)); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java index c833aec2258..1ab1abb7052 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ReturnNode; @@ -95,7 +96,7 @@ public class IntegerExactFoldTest extends GraalCompilerTest { ValueNode node = findNode(graph); boolean overflowExpected = node instanceof IntegerExactArithmeticNode; - IntegerStamp resultStamp = (IntegerStamp) node.stamp(); + IntegerStamp resultStamp = (IntegerStamp) node.stamp(NodeView.DEFAULT); operation.verifyOverflow(lowerBoundA, upperBoundA, lowerBoundB, upperBoundB, bits, overflowExpected, resultStamp); } @@ -120,7 +121,7 @@ public class IntegerExactFoldTest extends GraalCompilerTest { ValueNode node = findNode(graph); boolean overflowExpected = node instanceof IntegerExactArithmeticSplitNode; - IntegerStamp resultStamp = (IntegerStamp) node.stamp(); + IntegerStamp resultStamp = (IntegerStamp) node.stamp(NodeView.DEFAULT); operation.verifyOverflow(lowerBoundA, upperBoundA, lowerBoundB, upperBoundB, bits, overflowExpected, resultStamp); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java index cc02a21f970..f99d7adb323 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; @@ -50,8 +51,12 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public abstract class MethodSubstitutionTest extends GraalCompilerTest { - @SuppressWarnings("try") protected StructuredGraph testGraph(final String snippet) { + return testGraph(snippet, null); + } + + @SuppressWarnings("try") + protected StructuredGraph testGraph(final String snippet, String name) { DebugContext debug = getDebugContext(); try (DebugContext.Scope s = debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); @@ -69,7 +74,20 @@ public abstract class MethodSubstitutionTest extends GraalCompilerTest { new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context); } assertNotInGraph(graph, MacroNode.class); - assertNotInGraph(graph, Invoke.class); + if (name != null) { + for (Node node : graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + if (invoke.callTarget() instanceof MethodCallTargetNode) { + MethodCallTargetNode call = (MethodCallTargetNode) invoke.callTarget(); + assertTrue(!call.targetMethod().getName().equals(name), "Unexpected invoke of intrinsic %s", call.targetMethod()); + } + } + + } + } else { + assertNotInGraph(graph, Invoke.class); + } return graph; } catch (Throwable e) { throw debug.handle(e); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java index 090470f0c59..fd20ab92a7d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java @@ -221,7 +221,8 @@ public class MonitorTest extends GraalCompilerTest { * Reproduces issue reported in https://github.com/graalvm/graal-core/issues/201. The stamp in * the PiNode returned by {@link BoxingSnippets#longValueOf} was overwritten when the node was * subsequently canonicalized because {@code PiNode.computeValue()} ignored the - * {@link ValueNode#stamp()} field and used the {@code PiNode.piStamp} field. + * {@link ValueNode#stamp(org.graalvm.compiler.nodes.NodeView)} field and used the + * {@code PiNode.piStamp} field. */ @Test public void test8() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java index 95e0f45c7e2..7eb29a16c78 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.replacements.test; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -93,7 +94,7 @@ public class ObjectAccessTest extends SnippetsTest { private static void assertRead(StructuredGraph graph, JavaKind kind, boolean indexConvert, LocationIdentity locationIdentity) { JavaReadNode read = (JavaReadNode) graph.start().next(); - Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind()); + Assert.assertEquals(kind.getStackKind(), read.stamp(NodeView.DEFAULT).getStackKind()); OffsetAddressNode address = (OffsetAddressNode) read.getAddress(); Assert.assertEquals(graph.getParameter(0), address.getBase()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java index 9ebfb868398..48d6f19f8c3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.replacements.test; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -105,12 +106,12 @@ public class PointerTest extends SnippetsTest { WordCastNode cast = (WordCastNode) graph.start().next(); JavaReadNode read = (JavaReadNode) cast.next(); - Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind()); + Assert.assertEquals(kind.getStackKind(), read.stamp(NodeView.DEFAULT).getStackKind()); OffsetAddressNode address = (OffsetAddressNode) read.getAddress(); Assert.assertEquals(cast, address.getBase()); Assert.assertEquals(graph.getParameter(0), cast.getInput()); - Assert.assertEquals(target.wordJavaKind, cast.stamp().getStackKind()); + Assert.assertEquals(target.wordJavaKind, cast.stamp(NodeView.DEFAULT).getStackKind()); Assert.assertEquals(locationIdentity, read.getLocationIdentity()); @@ -137,7 +138,7 @@ public class PointerTest extends SnippetsTest { OffsetAddressNode address = (OffsetAddressNode) write.getAddress(); Assert.assertEquals(cast, address.getBase()); Assert.assertEquals(graph.getParameter(0), cast.getInput()); - Assert.assertEquals(target.wordJavaKind, cast.stamp().getStackKind()); + Assert.assertEquals(target.wordJavaKind, cast.stamp(NodeView.DEFAULT).getStackKind()); Assert.assertEquals(locationIdentity, write.getLocationIdentity()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SystemArrayCopyTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SystemArrayCopyTest.java new file mode 100644 index 00000000000..ee74c619b04 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SystemArrayCopyTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014, 2014, 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.graalvm.compiler.replacements.test; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ParameterNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import java.util.ArrayList; +import java.util.Collection; + +import static java.lang.reflect.Modifier.isStatic; + +@RunWith(Parameterized.class) +public class SystemArrayCopyTest extends GraalCompilerTest { + + @Parameter(0) public Object src; + @Parameter(1) public Object dst; + @Parameter(2) public int len; + @Parameter(3) public String name; + + @Parameters(name = "{3}") + public static Collection data() { + Object[] srcs = {new int[4], new double[4], new Integer[4], new Number[4], new String[4], new Object[]{"Graal", 0, 0, 0}, new Object()}; + Object[] dsts = {new int[4], new Number[4]}; + int[] lens = {-1, 0, 2, 8}; + + ArrayList ret = new ArrayList<>(srcs.length * dsts.length * lens.length); + for (Object src : srcs) { + for (Object dst : dsts) { + for (int length : lens) { + ret.add(new Object[]{src, dst, length, src.getClass().getSimpleName() + ", 0, " + dst.getClass().getSimpleName() + ", 0, " + length}); + } + } + } + return ret; + } + + public static void testArrayCopySnippet(Object src, Object dst, int length) { + System.arraycopy(src, 0, dst, 0, length); + } + + private static final int PARAMETER_LENGTH = 3; + private Object[] argsToBind; + + @Test + public void testArrayCopy() { + ResolvedJavaMethod method = getResolvedJavaMethod("testArrayCopySnippet"); + Object receiver = method.isStatic() ? null : this; + Object[] args = {src, dst, len}; + + Result expect = executeExpected(method, receiver, args); + testAgainstExpected(method, expect, receiver, args); + + // test composition of constant binding + for (int i = 1; i < (1 << PARAMETER_LENGTH); i++) { + argsToBind = new Object[PARAMETER_LENGTH]; + for (int j = 0; j < PARAMETER_LENGTH; j++) { + if ((i & (1 << j)) != 0) { + argsToBind[j] = args[j]; + } + } + testAgainstExpected(method, expect, receiver, args); + } + } + + @Override + protected StructuredGraph parse(StructuredGraph.Builder builder, PhaseSuite graphBuilderSuite) { + StructuredGraph graph = super.parse(builder, graphBuilderSuite); + if (argsToBind != null) { + ResolvedJavaMethod m = graph.method(); + Object receiver = isStatic(m.getModifiers()) ? null : this; + Object[] args = argsWithReceiver(receiver, argsToBind); + JavaType[] parameterTypes = m.toParameterTypes(); + assert parameterTypes.length == args.length; + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { + int index = param.index(); + if (args[index] != null) { + JavaConstant c = getSnippetReflection().forBoxed(parameterTypes[index].getJavaKind(), args[index]); + ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph); + param.replaceAtUsages(replacement); + } + } + } + return graph; + } + + @Override + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + return super.getCode(method, graph, true, installAsDefault, options); + } + +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index dd0746320f3..4bfcadde273 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -58,6 +58,7 @@ import org.graalvm.compiler.nodes.FieldLocationIdentity; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -113,7 +114,6 @@ import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; -import org.graalvm.compiler.nodes.memory.address.RawAddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -247,7 +247,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { indexOfSnippets.lower(node, tool); } }; - SnippetLowerableMemoryNode snippetLower = new SnippetLowerableMemoryNode(lowering, NamedLocationIdentity.getArrayLocation(JavaKind.Char), n.stamp(), n.toArgumentArray()); + SnippetLowerableMemoryNode snippetLower = new SnippetLowerableMemoryNode(lowering, NamedLocationIdentity.getArrayLocation(JavaKind.Char), n.stamp(NodeView.DEFAULT), n.toArgumentArray()); n.graph().add(snippetLower); n.graph().replaceFixedWithFixed(n, snippetLower); } @@ -347,7 +347,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { ResolvedJavaField field = loadField.field(); ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object(); object = createNullCheckedValue(object, loadField, tool); - Stamp loadStamp = loadStamp(loadField.stamp(), getStorageKind(field)); + Stamp loadStamp = loadStamp(loadField.stamp(NodeView.DEFAULT), getStorageKind(field)); AddressNode address = createFieldAddress(graph, object, field); assert address != null : "Field that is loaded must not be eliminated: " + field.getDeclaringClass().toJavaName(true) + "." + field.getName(); @@ -419,7 +419,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { ValueNode array = loadIndexed.array(); array = createNullCheckedValue(array, loadIndexed, tool); JavaKind elementKind = loadIndexed.elementKind(); - Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind); + Stamp loadStamp = loadStamp(loadIndexed.stamp(NodeView.DEFAULT), elementKind); GuardingNode boundsCheck = getBoundsCheck(loadIndexed, array, tool); AddressNode address = createArrayIndexAddress(graph, array, elementKind, loadIndexed.index(), boundsCheck); @@ -575,7 +575,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { protected AddressNode createUnsafeAddress(StructuredGraph graph, ValueNode object, ValueNode offset) { if (object.isConstant() && object.asConstant().isDefaultForKind()) { - return graph.unique(new RawAddressNode(offset)); + return graph.addOrUniqueWithInputs(OffsetAddressNode.create(offset)); } else { return graph.unique(new OffsetAddressNode(object, offset)); } @@ -584,7 +584,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { protected ReadNode createUnsafeRead(StructuredGraph graph, RawLoadNode load, GuardingNode guard) { boolean compressible = load.accessKind() == JavaKind.Object; JavaKind readKind = load.accessKind(); - Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); + Stamp loadStamp = loadStamp(load.stamp(NodeView.DEFAULT), readKind, compressible); AddressNode address = createUnsafeAddress(graph, load.object(), load.offset()); ReadNode memoryRead = graph.add(new ReadNode(address, load.getLocationIdentity(), loadStamp, BarrierType.NONE)); if (guard == null) { @@ -603,8 +603,8 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { StructuredGraph graph = load.graph(); JavaKind readKind = load.getKind(); assert readKind != JavaKind.Object; - Stamp loadStamp = loadStamp(load.stamp(), readKind, false); - AddressNode address = graph.unique(new RawAddressNode(load.getAddress())); + Stamp loadStamp = loadStamp(load.stamp(NodeView.DEFAULT), readKind, false); + AddressNode address = graph.addOrUniqueWithInputs(OffsetAddressNode.create(load.getAddress())); ReadNode memoryRead = graph.add(new ReadNode(address, load.getLocationIdentity(), loadStamp, BarrierType.NONE)); // An unsafe read must not float otherwise it may float above // a test guaranteeing the read is safe. @@ -639,7 +639,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { assert store.getValue().getStackKind() != JavaKind.Object; JavaKind valueKind = store.getKind(); ValueNode value = implicitStoreConvert(graph, valueKind, store.getValue(), false); - AddressNode address = graph.unique(new RawAddressNode(store.getAddress())); + AddressNode address = graph.addOrUniqueWithInputs(OffsetAddressNode.create(store.getAddress())); WriteNode write = graph.add(new WriteNode(address, store.getLocationIdentity(), value, BarrierType.NONE)); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); @@ -648,7 +648,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { protected void lowerJavaReadNode(JavaReadNode read) { StructuredGraph graph = read.graph(); JavaKind valueKind = read.getReadKind(); - Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible()); + Stamp loadStamp = loadStamp(read.stamp(NodeView.DEFAULT), valueKind, read.isCompressible()); ReadNode memoryRead = graph.add(new ReadNode(read.getAddress(), read.getLocationIdentity(), loadStamp, read.getBarrierType())); GuardingNode guard = read.getGuard(); @@ -1041,7 +1041,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { arrayLength = arrayLength.isAlive() ? arrayLength : graph.addOrUniqueWithInputs(arrayLength); } - LogicNode boundsCheck = IntegerBelowNode.create(n.index(), arrayLength); + LogicNode boundsCheck = IntegerBelowNode.create(n.index(), arrayLength, NodeView.DEFAULT); if (boundsCheck.isTautology()) { return null; } @@ -1060,7 +1060,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { if (nullCheck == null) { return object; } - return before.graph().maybeAddOrUnique(PiNode.create(object, (object.stamp()).join(StampFactory.objectNonNull()), (ValueNode) nullCheck)); + return before.graph().maybeAddOrUnique(PiNode.create(object, (object.stamp(NodeView.DEFAULT)).join(StampFactory.objectNonNull()), (ValueNode) nullCheck)); } @Override @@ -1069,10 +1069,10 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { ValueNode offset = ((OffsetAddressNode) address).getOffset(); int base = arrayBaseOffset(elementKind); - ValueNode scaledIndex = graph.unique(new SubNode(offset, ConstantNode.forIntegerStamp(offset.stamp(), base, graph))); + ValueNode scaledIndex = graph.unique(new SubNode(offset, ConstantNode.forIntegerStamp(offset.stamp(NodeView.DEFAULT), base, graph))); int shift = CodeUtil.log2(arrayScalingFactor(elementKind)); ValueNode ret = graph.unique(new RightShiftNode(scaledIndex, ConstantNode.forInt(shift, graph))); - return IntegerConvertNode.convert(ret, StampFactory.forKind(JavaKind.Int), graph); + return IntegerConvertNode.convert(ret, StampFactory.forKind(JavaKind.Int), graph, NodeView.DEFAULT); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java index 99d6ff7d413..6ccd8d4f91d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java @@ -50,6 +50,7 @@ import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.KillingBeginNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; @@ -271,12 +272,12 @@ public class GraphKit implements GraphBuilderTool { int argIndex = 0; if (!isStatic) { JavaKind expected = asKind(method.getDeclaringClass()); - JavaKind actual = args[argIndex++].stamp().getStackKind(); + JavaKind actual = args[argIndex++].stamp(NodeView.DEFAULT).getStackKind(); assert expected == actual : graph + ": wrong kind of value for receiver argument of call to " + method + " [" + actual + " != " + expected + "]"; } for (int i = 0; i != signature.getParameterCount(false); i++) { JavaKind expected = asKind(signature.getParameterType(i, method.getDeclaringClass())).getStackKind(); - JavaKind actual = args[argIndex++].stamp().getStackKind(); + JavaKind actual = args[argIndex++].stamp(NodeView.DEFAULT).getStackKind(); if (expected != actual) { throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of call to " + method + " [" + actual + " != " + expected + "]"); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java index bea1cd94df3..0f0440ddaf0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ShortCircuitOrNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -183,7 +184,7 @@ public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { } if (condition == null || (!(condition instanceof CompareNode)) || ((CompareNode) condition).getY() != testValue) { // Re-use previously generated condition if the trueValue for the test is the same - condition = createCompareNode(result.graph(), Condition.EQ, result, testValue, null); + condition = createCompareNode(result.graph(), Condition.EQ, result, testValue, null, NodeView.DEFAULT); } return condition; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java index b7027451717..48ebe3e562e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java @@ -83,6 +83,10 @@ public class MethodHandlePlugin implements NodePlugin { // As such, it needs to recursively inline everything. inlineEverything = args.length != argumentsList.size(); } + if (inlineEverything && !callTarget.targetMethod().hasBytecodes()) { + // we need to force-inline but we can not, leave the invoke as-is + return false; + } b.handleReplacedInvoke(invoke.getInvokeKind(), callTarget.targetMethod(), argumentsList.toArray(new ValueNode[argumentsList.size()]), inlineEverything); } return true; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index 1509b364545..aa52ee525d8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -63,6 +63,7 @@ import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; @@ -583,7 +584,7 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder { return callTarget.targetMethod(); } - SpecialCallTargetCacheKey key = new SpecialCallTargetCacheKey(callTarget.invokeKind(), callTarget.targetMethod(), invokeData.contextType, callTarget.receiver().stamp()); + SpecialCallTargetCacheKey key = new SpecialCallTargetCacheKey(callTarget.invokeKind(), callTarget.targetMethod(), invokeData.contextType, callTarget.receiver().stamp(NodeView.DEFAULT)); Object specialCallTarget = specialCallTargetCache.get(key); if (specialCallTarget == null) { specialCallTarget = MethodCallTargetNode.devirtualizeCall(key.invokeKind, key.targetMethod, key.contextType, graph.getAssumptions(), @@ -1066,7 +1067,7 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder { assert !methodScope.isInlinedMethod(); GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, null); Node result = parameterPlugin.interceptParameter(graphBuilderContext, param.index(), - StampPair.create(param.stamp(), param.uncheckedStamp())); + StampPair.create(param.stamp(NodeView.DEFAULT), param.uncheckedStamp())); if (result != null) { return result; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 067fde637bd..45258eac938 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -83,6 +83,7 @@ import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode.Placeholder; @@ -750,7 +751,7 @@ public class SnippetTemplate { nodeReplacements.put(parameter, placeholder); placeholders[i] = placeholder; } else if (args.info.isNonNullParameter(i)) { - parameter.setStamp(parameter.stamp().join(StampFactory.objectNonNull())); + parameter.setStamp(parameter.stamp(NodeView.DEFAULT).join(StampFactory.objectNonNull())); } } } @@ -785,7 +786,8 @@ public class SnippetTemplate { if (usage instanceof LoadIndexedNode) { LoadIndexedNode loadIndexed = (LoadIndexedNode) usage; debug.dump(DebugContext.INFO_LEVEL, snippetCopy, "Before replacing %s", loadIndexed); - LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(new LoadSnippetVarargParameterNode(params, loadIndexed.index(), loadIndexed.stamp())); + LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add( + new LoadSnippetVarargParameterNode(params, loadIndexed.index(), loadIndexed.stamp(NodeView.DEFAULT))); snippetCopy.replaceFixedWithFixed(loadIndexed, loadSnippetParameter); debug.dump(DebugContext.INFO_LEVEL, snippetCopy, "After replacing %s", loadIndexed); } else if (usage instanceof StoreIndexedNode) { @@ -829,7 +831,7 @@ public class SnippetTemplate { for (Node node : snippetCopy.getNodes()) { if (node instanceof ValueNode) { ValueNode valueNode = (ValueNode) node; - if (valueNode.stamp() == PlaceholderStamp.singleton()) { + if (valueNode.stamp(NodeView.DEFAULT) == PlaceholderStamp.singleton()) { curPlaceholderStampedNodes.add(valueNode); } } @@ -1502,7 +1504,7 @@ public class SnippetTemplate { private void updateStamps(ValueNode replacee, UnmodifiableEconomicMap duplicates) { for (ValueNode node : placeholderStampedNodes) { ValueNode dup = (ValueNode) duplicates.get(node); - Stamp replaceeStamp = replacee.stamp(); + Stamp replaceeStamp = replacee.stamp(NodeView.DEFAULT); if (node instanceof Placeholder) { Placeholder placeholderDup = (Placeholder) dup; placeholderDup.makeReplacement(replaceeStamp); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java index 9bd73d2d322..ba074f3a9c4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java @@ -54,6 +54,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AbsNode; @@ -296,14 +297,14 @@ public class StandardGraphBuilderPlugins { r.register2("divideUnsigned", type, type, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode dividend, ValueNode divisor) { - b.push(kind, b.append(new UnsignedDivNode(dividend, divisor).canonical(null))); + b.push(kind, b.append(UnsignedDivNode.create(dividend, divisor, NodeView.DEFAULT))); return true; } }); r.register2("remainderUnsigned", type, type, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode dividend, ValueNode divisor) { - b.push(kind, b.append(new UnsignedRemNode(dividend, divisor).canonical(null))); + b.push(kind, b.append(UnsignedRemNode.create(dividend, divisor, NodeView.DEFAULT))); return true; } }); @@ -344,14 +345,14 @@ public class StandardGraphBuilderPlugins { r.register1("floatToRawIntBits", float.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(JavaKind.Int, b.append(new ReinterpretNode(JavaKind.Int, value).canonical(null))); + b.push(JavaKind.Int, b.append(ReinterpretNode.create(JavaKind.Int, value, NodeView.DEFAULT))); return true; } }); r.register1("intBitsToFloat", int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(JavaKind.Float, b.append(new ReinterpretNode(JavaKind.Float, value).canonical(null))); + b.push(JavaKind.Float, b.append(ReinterpretNode.create(JavaKind.Float, value, NodeView.DEFAULT))); return true; } }); @@ -362,14 +363,14 @@ public class StandardGraphBuilderPlugins { r.register1("doubleToRawLongBits", double.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(JavaKind.Long, b.append(new ReinterpretNode(JavaKind.Long, value).canonical(null))); + b.push(JavaKind.Long, b.append(ReinterpretNode.create(JavaKind.Long, value, NodeView.DEFAULT))); return true; } }); r.register1("longBitsToDouble", long.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(JavaKind.Double, b.append(new ReinterpretNode(JavaKind.Double, value).canonical(null))); + b.push(JavaKind.Double, b.append(ReinterpretNode.create(JavaKind.Double, value, NodeView.DEFAULT))); return true; } }); @@ -421,7 +422,7 @@ public class StandardGraphBuilderPlugins { r.register1("sqrt", Double.TYPE, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(JavaKind.Double, b.append(new SqrtNode(value).canonical(null))); + b.push(JavaKind.Double, b.append(SqrtNode.create(value, NodeView.DEFAULT))); return true; } }); @@ -470,7 +471,7 @@ public class StandardGraphBuilderPlugins { cond = cond.negate(); } - LogicNode compare = CompareNode.createCompareNode(graph, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, cond, lhs, rhs); + LogicNode compare = CompareNode.createCompareNode(graph, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, cond, lhs, rhs, NodeView.DEFAULT); b.addPush(JavaKind.Boolean, new ConditionalNode(compare, trueValue, falseValue)); return true; } @@ -521,7 +522,7 @@ public class StandardGraphBuilderPlugins { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { ValueNode object = receiver.get(); - ValueNode folded = GetClassNode.tryFold(b.getMetaAccess(), b.getConstantReflection(), GraphUtil.originalValue(object)); + ValueNode folded = GetClassNode.tryFold(b.getMetaAccess(), b.getConstantReflection(), NodeView.DEFAULT, GraphUtil.originalValue(object)); if (folded != null) { b.addPush(JavaKind.Object, folded); } else { @@ -892,7 +893,8 @@ public class StandardGraphBuilderPlugins { } else if (falseCount == 0 || trueCount == 0) { boolean expected = falseCount == 0; LogicNode condition = b.addWithInputs( - IntegerEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, result, b.add(ConstantNode.forBoolean(!expected)))); + IntegerEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, result, b.add(ConstantNode.forBoolean(!expected)), + NodeView.DEFAULT)); b.append(new FixedGuardNode(condition, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, true)); newResult = b.add(ConstantNode.forBoolean(expected)); } else { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java index a08ff3182cc..9f62f4d66bb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValueNodeUtil; import org.graalvm.compiler.nodes.memory.MemoryAccess; @@ -173,7 +174,7 @@ public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLower allEqual = false; } } - if (entry1.stamp().alwaysDistinct(entry2.stamp())) { + if (entry1.stamp(NodeView.DEFAULT).alwaysDistinct(entry2.stamp(NodeView.DEFAULT))) { // the contents are different tool.replaceWithValue(ConstantNode.forBoolean(false, graph())); return; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java index 0c5e6a17724..a8c9eca51f7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; @@ -164,8 +165,8 @@ public class BasicArrayCopyNode extends AbstractMemoryCheckpoint implements Virt * Returns true if this copy doesn't require store checks. Trivially true for primitive arrays. */ public boolean isExact() { - ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp()); - ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp()); + ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp(NodeView.DEFAULT)); + ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp(NodeView.DEFAULT)); if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { return false; } @@ -173,7 +174,7 @@ public class BasicArrayCopyNode extends AbstractMemoryCheckpoint implements Virt return true; } - if (StampTool.isExactType(getDestination().stamp())) { + if (StampTool.isExactType(getDestination().stamp(NodeView.DEFAULT))) { if (destType != null && destType.isAssignableFrom(srcType)) { return true; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java index 9261266c0eb..a053795a24f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; @@ -65,7 +66,7 @@ public abstract class BasicObjectCloneNode extends MacroStateSplitNode implement } protected Stamp computeStamp(ValueNode object) { - Stamp objectStamp = object.stamp(); + Stamp objectStamp = object.stamp(NodeView.DEFAULT); if (objectStamp instanceof ObjectStamp) { objectStamp = objectStamp.join(StampFactory.objectNonNull()); } @@ -116,7 +117,7 @@ public abstract class BasicObjectCloneNode extends MacroStateSplitNode implement tool.replaceWithVirtual(newVirtual); } } else { - ResolvedJavaType type = getConcreteType(originalAlias.stamp()); + ResolvedJavaType type = getConcreteType(originalAlias.stamp(NodeView.DEFAULT)); if (type != null && !type.isArray()) { VirtualInstanceNode newVirtual = createVirtualInstanceNode(type, true); ResolvedJavaField[] fields = newVirtual.getFields(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BinaryMathIntrinsicNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BinaryMathIntrinsicNode.java index 2e68bc7e6b8..e2fad1dfccc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BinaryMathIntrinsicNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BinaryMathIntrinsicNode.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.BinaryNode; import org.graalvm.compiler.nodes.calc.FloatDivNode; @@ -86,13 +87,13 @@ public final class BinaryMathIntrinsicNode extends BinaryNode implements Arithme @Override public Stamp foldStamp(Stamp stampX, Stamp stampY) { - return stamp(); + return stamp(NodeView.DEFAULT); } protected BinaryMathIntrinsicNode(ValueNode forX, ValueNode forY, BinaryOperation op) { super(TYPE, StampFactory.forKind(JavaKind.Double), forX, forY); - assert forX.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(forX.stamp()) == 64; - assert forY.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(forY.stamp()) == 64; + assert forX.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(forX.stamp(NodeView.DEFAULT)) == 64; + assert forY.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(forY.stamp(NodeView.DEFAULT)) == 64; this.operation = op; } @@ -118,6 +119,7 @@ public final class BinaryMathIntrinsicNode extends BinaryNode implements Arithme @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + NodeView view = NodeView.from(tool); ValueNode c = tryConstantFold(forX, forY, getOperation()); if (c != null) { return c; @@ -150,8 +152,8 @@ public final class BinaryMathIntrinsicNode extends BinaryNode implements Arithme } // x**0.5 = sqrt(x) - if (yValue == 0.5D && x.stamp() instanceof FloatStamp && ((FloatStamp) x.stamp()).lowerBound() >= 0.0D) { - return new SqrtNode(x); + if (yValue == 0.5D && x.stamp(view) instanceof FloatStamp && ((FloatStamp) x.stamp(view)).lowerBound() >= 0.0D) { + return SqrtNode.create(x, view); } } return this; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java index 864e9b569f7..a1868016324 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -48,7 +49,7 @@ public final class BitCountNode extends UnaryNode implements ArithmeticLIRLowera public static final NodeClass TYPE = NodeClass.create(BitCountNode.class); public BitCountNode(ValueNode value) { - super(TYPE, computeStamp(value.stamp(), value), value); + super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), value), value); assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; } @@ -59,7 +60,7 @@ public final class BitCountNode extends UnaryNode implements ArithmeticLIRLowera } static Stamp computeStamp(Stamp newStamp, ValueNode theValue) { - assert newStamp.isCompatible(theValue.stamp()); + assert newStamp.isCompatible(theValue.stamp(NodeView.DEFAULT)); IntegerStamp valueStamp = (IntegerStamp) newStamp; assert (valueStamp.downMask() & CodeUtil.mask(valueStamp.getBits())) == valueStamp.downMask(); assert (valueStamp.upMask() & CodeUtil.mask(valueStamp.getBits())) == valueStamp.upMask(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanForwardNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanForwardNode.java index 80d3d8d61a6..b9d1f50056a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanForwardNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanForwardNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -53,13 +54,13 @@ public final class BitScanForwardNode extends UnaryNode implements ArithmeticLIR public static final NodeClass TYPE = NodeClass.create(BitScanForwardNode.class); public BitScanForwardNode(ValueNode value) { - super(TYPE, StampFactory.forInteger(JavaKind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + super(TYPE, StampFactory.forInteger(JavaKind.Int, 0, ((PrimitiveStamp) value.stamp(NodeView.DEFAULT)).getBits()), value); assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; } @Override public Stamp foldStamp(Stamp newStamp) { - assert newStamp.isCompatible(getValue().stamp()); + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); IntegerStamp valueStamp = (IntegerStamp) newStamp; int min; int max; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanReverseNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanReverseNode.java index bf9be6929fb..9dc9ac98ca4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanReverseNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanReverseNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -53,13 +54,13 @@ public final class BitScanReverseNode extends UnaryNode implements ArithmeticLIR public static final NodeClass TYPE = NodeClass.create(BitScanReverseNode.class); public BitScanReverseNode(ValueNode value) { - super(TYPE, StampFactory.forInteger(JavaKind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + super(TYPE, StampFactory.forInteger(JavaKind.Int, 0, ((PrimitiveStamp) value.stamp(NodeView.DEFAULT)).getBits()), value); assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; } @Override public Stamp foldStamp(Stamp newStamp) { - assert newStamp.isCompatible(getValue().stamp()); + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); IntegerStamp valueStamp = (IntegerStamp) newStamp; int min; int max; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java index 604a9987ea8..bc78260f0c4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java @@ -44,6 +44,7 @@ import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.LogicNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -263,7 +264,7 @@ public final class MethodHandleNode extends MacroStateSplitNode implements Simpl // Try to get the most accurate receiver type if (intrinsicMethod == IntrinsicMethod.LINK_TO_VIRTUAL || intrinsicMethod == IntrinsicMethod.LINK_TO_INTERFACE) { ValueNode receiver = getReceiver(originalArguments); - TypeReference receiverType = StampTool.typeReferenceOrNull(receiver.stamp()); + TypeReference receiverType = StampTool.typeReferenceOrNull(receiver.stamp(NodeView.DEFAULT)); if (receiverType != null) { concreteMethod = receiverType.getType().findUniqueConcreteMethod(target); } @@ -317,7 +318,7 @@ public final class MethodHandleNode extends MacroStateSplitNode implements Simpl * type information anyway. */ if (targetType != null && !targetType.getType().isPrimitive() && !argument.getStackKind().isPrimitive()) { - ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); + ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp(NodeView.DEFAULT)); if (argumentType == null || (argumentType.isAssignableFrom(targetType.getType()) && !argumentType.equals(targetType.getType()))) { LogicNode inst = InstanceOfNode.createAllowNull(targetType, argument, null, null); assert !inst.isAlive(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java index ff5d7658706..e46bf3af591 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -82,7 +83,7 @@ public final class ReadRegisterNode extends FixedWithNextNode implements LIRLowe @Override public void generate(NodeLIRBuilderTool generator) { - LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp()); + LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); Value result = register.asValue(kind); if (incoming) { generator.getLIRGeneratorTool().emitIncomingValues(new Value[]{result}); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReverseBytesNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReverseBytesNode.java index 414a7632938..5ad14522c51 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReverseBytesNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReverseBytesNode.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -54,7 +55,7 @@ public final class ReverseBytesNode extends UnaryNode implements LIRLowerable { @Override public Stamp foldStamp(Stamp newStamp) { - assert newStamp.isCompatible(getValue().stamp()); + assert newStamp.isCompatible(getValue().stamp(NodeView.DEFAULT)); IntegerStamp valueStamp = (IntegerStamp) newStamp; if (getStackKind() == JavaKind.Int) { long mask = CodeUtil.mask(JavaKind.Int.getBitCount()); @@ -62,7 +63,7 @@ public final class ReverseBytesNode extends UnaryNode implements LIRLowerable { } else if (getStackKind() == JavaKind.Long) { return IntegerStamp.stampForMask(valueStamp.getBits(), Long.reverse(valueStamp.downMask()), Long.reverse(valueStamp.upMask())); } else { - return stamp(); + return stamp(NodeView.DEFAULT); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/UnaryMathIntrinsicNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/UnaryMathIntrinsicNode.java index 390c96af042..77d2c6d94dc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/UnaryMathIntrinsicNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/UnaryMathIntrinsicNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.UnaryNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; @@ -106,8 +107,8 @@ public final class UnaryMathIntrinsicNode extends UnaryNode implements Arithmeti } protected UnaryMathIntrinsicNode(ValueNode value, UnaryOperation op) { - super(TYPE, computeStamp(value.stamp(), op), value); - assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64; + super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), op), value); + assert value.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp(NodeView.DEFAULT)) == 64; this.operation = op; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactNode.java index bc6ae830e95..f22225b1e7d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -54,8 +55,8 @@ public final class IntegerAddExactNode extends AddNode implements IntegerExactAr public IntegerAddExactNode(ValueNode x, ValueNode y) { super(TYPE, x, y); - setStamp(x.stamp().unrestricted()); - assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; + setStamp(x.stamp(NodeView.DEFAULT).unrestricted()); + assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)) && x.stamp(NodeView.DEFAULT) instanceof IntegerStamp; } @Override @@ -132,7 +133,7 @@ public final class IntegerAddExactNode extends AddNode implements IntegerExactAr return forX; } } - if (!IntegerStamp.addCanOverflow((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) { + if (!IntegerStamp.addCanOverflow((IntegerStamp) forX.stamp(NodeView.DEFAULT), (IntegerStamp) forY.stamp(NodeView.DEFAULT))) { return new AddNode(forX, forY).canonical(tool); } return this; @@ -159,7 +160,7 @@ public final class IntegerAddExactNode extends AddNode implements IntegerExactAr @Override public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { - return graph().add(new IntegerAddExactSplitNode(stamp(), getX(), getY(), next, deopt)); + return graph().add(new IntegerAddExactSplitNode(stamp(NodeView.DEFAULT), getX(), getY(), next, deopt)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactSplitNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactSplitNode.java index 43bb3993c3c..5e909f8e165 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactSplitNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactSplitNode.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -49,7 +50,8 @@ public final class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitN @Override public void simplify(SimplifierTool tool) { - if (!IntegerStamp.addCanOverflow((IntegerStamp) x.stamp(), (IntegerStamp) y.stamp())) { + NodeView view = NodeView.from(tool); + if (!IntegerStamp.addCanOverflow((IntegerStamp) x.stamp(view), (IntegerStamp) y.stamp(view))) { tool.deleteBranch(overflowSuccessor); tool.addToWorkList(next); AddNode replacement = graph().unique(new AddNode(x, y)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactNode.java index f4781e44123..f3656b3b5f0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -48,8 +49,8 @@ public final class IntegerMulExactNode extends MulNode implements IntegerExactAr public IntegerMulExactNode(ValueNode x, ValueNode y) { super(TYPE, x, y); - setStamp(x.stamp().unrestricted()); - assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; + setStamp(x.stamp(NodeView.DEFAULT).unrestricted()); + assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)) && x.stamp(NodeView.DEFAULT) instanceof IntegerStamp; } @Override @@ -76,10 +77,10 @@ public final class IntegerMulExactNode extends MulNode implements IntegerExactAr return forX; } if (c == 0) { - return ConstantNode.forIntegerStamp(stamp(), 0); + return ConstantNode.forIntegerStamp(stamp(NodeView.DEFAULT), 0); } } - if (!IntegerStamp.multiplicationCanOverflow((IntegerStamp) x.stamp(), (IntegerStamp) y.stamp())) { + if (!IntegerStamp.multiplicationCanOverflow((IntegerStamp) x.stamp(NodeView.DEFAULT), (IntegerStamp) y.stamp(NodeView.DEFAULT))) { return new MulNode(x, y).canonical(tool); } return this; @@ -104,7 +105,7 @@ public final class IntegerMulExactNode extends MulNode implements IntegerExactAr @Override public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { - return graph().add(new IntegerMulExactSplitNode(stamp(), getX(), getY(), next, deopt)); + return graph().add(new IntegerMulExactSplitNode(stamp(NodeView.DEFAULT), getX(), getY(), next, deopt)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactSplitNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactSplitNode.java index c7d4492e53d..aff76b1d4e4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactSplitNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactSplitNode.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -51,7 +52,8 @@ public final class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitN @Override public void simplify(SimplifierTool tool) { - if (!IntegerStamp.multiplicationCanOverflow((IntegerStamp) x.stamp(), (IntegerStamp) y.stamp())) { + NodeView view = NodeView.from(tool); + if (!IntegerStamp.multiplicationCanOverflow((IntegerStamp) x.stamp(view), (IntegerStamp) y.stamp(view))) { tool.deleteBranch(overflowSuccessor); tool.addToWorkList(next); MulNode replacement = graph().unique(new MulNode(x, y)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulHighNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulHighNode.java index 2a7107ef435..13c381dc6fc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulHighNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulHighNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -81,7 +82,7 @@ public final class IntegerMulHighNode extends BinaryArithmeticNode impl if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { long i = ((PrimitiveConstant) c).asLong(); if (i == 0 || i == 1) { - return ConstantNode.forIntegerStamp(self.stamp(), 0); + return ConstantNode.forIntegerStamp(self.stamp(NodeView.DEFAULT), 0); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactNode.java index 625dbf6f7d0..d9a4ede5b95 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -49,8 +50,8 @@ public final class IntegerSubExactNode extends SubNode implements IntegerExactAr public IntegerSubExactNode(ValueNode x, ValueNode y) { super(TYPE, x, y); - setStamp(x.stamp().unrestricted()); - assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; + setStamp(x.stamp(NodeView.DEFAULT).unrestricted()); + assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)) && x.stamp(NodeView.DEFAULT) instanceof IntegerStamp; } @Override @@ -67,7 +68,7 @@ public final class IntegerSubExactNode extends SubNode implements IntegerExactAr @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return ConstantNode.forIntegerStamp(stamp(), 0); + return ConstantNode.forIntegerStamp(stamp(NodeView.DEFAULT), 0); } if (forX.isConstant() && forY.isConstant()) { return canonicalXYconstant(forX, forY); @@ -77,7 +78,7 @@ public final class IntegerSubExactNode extends SubNode implements IntegerExactAr return forX; } } - if (!IntegerStamp.subtractionCanOverflow((IntegerStamp) x.stamp(), (IntegerStamp) y.stamp())) { + if (!IntegerStamp.subtractionCanOverflow((IntegerStamp) x.stamp(NodeView.DEFAULT), (IntegerStamp) y.stamp(NodeView.DEFAULT))) { return new SubNode(x, y).canonical(tool); } return this; @@ -102,7 +103,7 @@ public final class IntegerSubExactNode extends SubNode implements IntegerExactAr @Override public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { - return graph().add(new IntegerSubExactSplitNode(stamp(), getX(), getY(), next, deopt)); + return graph().add(new IntegerSubExactSplitNode(stamp(NodeView.DEFAULT), getX(), getY(), next, deopt)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactSplitNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactSplitNode.java index ad6ad0f808e..acd86ca9995 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactSplitNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactSplitNode.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -49,7 +50,8 @@ public final class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitN @Override public void simplify(SimplifierTool tool) { - if (!IntegerStamp.subtractionCanOverflow((IntegerStamp) x.stamp(), (IntegerStamp) y.stamp())) { + NodeView view = NodeView.from(tool); + if (!IntegerStamp.subtractionCanOverflow((IntegerStamp) x.stamp(view), (IntegerStamp) y.stamp(view))) { tool.deleteBranch(overflowSuccessor); tool.addToWorkList(next); SubNode replacement = graph().unique(new SubNode(x, y)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/UnsignedMulHighNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/UnsignedMulHighNode.java index ff0d7d1ceca..c0554681a7c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/UnsignedMulHighNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/UnsignedMulHighNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -81,7 +82,7 @@ public final class UnsignedMulHighNode extends BinaryArithmeticNode im if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { long i = ((PrimitiveConstant) c).asLong(); if (i == 0 || i == 1) { - return ConstantNode.forIntegerStamp(self.stamp(), 0); + return ConstantNode.forIntegerStamp(self.stamp(NodeView.DEFAULT), 0); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java index d880f8dd5cb..9dae16eef14 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ProxyNode; @@ -228,7 +229,8 @@ public final class GraphEffectList extends EffectList { */ public void replaceAtUsages(ValueNode node, ValueNode replacement, FixedNode insertBefore) { assert node != null && replacement != null : node + " " + replacement; - assert node.stamp().isCompatible(replacement.stamp()) : "Replacement node stamp not compatible " + node.stamp() + " vs " + replacement.stamp(); + assert node.stamp(NodeView.DEFAULT).isCompatible(replacement.stamp(NodeView.DEFAULT)) : "Replacement node stamp not compatible " + node.stamp(NodeView.DEFAULT) + " vs " + + replacement.stamp(NodeView.DEFAULT); add("replace at usages", (graph, obsoleteNodes) -> { assert node.isAlive(); ValueNode replacementNode = graph.addOrUniqueWithInputs(replacement); @@ -244,8 +246,8 @@ public final class GraphEffectList extends EffectList { * to improve the stamp information of the read. Such a read might later be replaced * with a read with a less precise stamp. */ - if (!node.stamp().equals(replacementNode.stamp())) { - replacementNode = graph.unique(new PiNode(replacementNode, node.stamp())); + if (!node.stamp(NodeView.DEFAULT).equals(replacementNode.stamp(NodeView.DEFAULT))) { + replacementNode = graph.unique(new PiNode(replacementNode, node.stamp(NodeView.DEFAULT))); } node.replaceAtUsages(replacementNode); if (node instanceof FixedWithNextNode) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java index b4722d8f9b5..5403efad0a3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.FieldLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode; @@ -127,7 +128,7 @@ public final class PEReadEliminationBlockState extends PartialEscapeBlockState

newIdentifier = identifier.duplicateWithObject(phi); - PhiNode phiNode = getCachedPhi(newIdentifier, values[0].stamp().unrestricted()); + PhiNode phiNode = getCachedPhi(newIdentifier, values[0].stamp(NodeView.DEFAULT).unrestricted()); mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi"); for (int i = 0; i < values.length; i++) { setPhiInput(phiNode, i, values[i]); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java index bae52ff242c..314d2d97dd1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.calc.UnpackEndianHalfNode; @@ -179,7 +180,7 @@ class VirtualizerToolImpl implements VirtualizerTool, CanonicalizerTool { } else if (oldValue.getStackKind() == JavaKind.Double || oldValue.getStackKind() == JavaKind.Long) { // Splitting double word constant by storing over it with an int getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing second half of double word value %s", current, oldValue); - ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false); + ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false, NodeView.DEFAULT); addNode(secondHalf); state.setEntry(virtual.getObjectId(), index + 1, secondHalf); } @@ -188,7 +189,7 @@ class VirtualizerToolImpl implements VirtualizerTool, CanonicalizerTool { // Storing into second half of double, so replace previous value ValueNode previous = getEntry(virtual, index - 1); getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing first half of double word value %s", current, previous); - ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true); + ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true, NodeView.DEFAULT); addNode(firstHalf); state.setEntry(virtual.getObjectId(), index - 1, firstHalf); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordCastNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordCastNode.java index 9b43b013a6c..41abd8cc3e9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordCastNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordCastNode.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -73,17 +74,17 @@ public final class WordCastNode extends FixedWithNextNode implements LIRLowerabl } public static WordCastNode addressToWord(ValueNode input, JavaKind wordKind) { - assert input.stamp() instanceof AbstractPointerStamp; + assert input.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp; return new WordCastNode(StampFactory.forKind(wordKind), input); } public static WordCastNode objectToTrackedPointer(ValueNode input, JavaKind wordKind) { - assert input.stamp() instanceof ObjectStamp; + assert input.stamp(NodeView.DEFAULT) instanceof ObjectStamp; return new WordCastNode(StampFactory.forKind(wordKind), input, true); } public static WordCastNode objectToUntrackedPointer(ValueNode input, JavaKind wordKind) { - assert input.stamp() instanceof ObjectStamp; + assert input.stamp(NodeView.DEFAULT) instanceof ObjectStamp; return new WordCastNode(StampFactory.forKind(wordKind), input, false); } @@ -108,13 +109,13 @@ public final class WordCastNode extends FixedWithNextNode implements LIRLowerabl return input; } - assert !stamp().isCompatible(input.stamp()); + assert !stamp(NodeView.DEFAULT).isCompatible(input.stamp(NodeView.DEFAULT)); if (input.isConstant()) { /* Null pointers are uncritical for GC, so they can be constant folded. */ if (input.asJavaConstant().isNull()) { - return ConstantNode.forIntegerStamp(stamp(), 0); + return ConstantNode.forIntegerStamp(stamp(NodeView.DEFAULT), 0); } else if (input.asJavaConstant().getJavaKind().isNumericInteger() && input.asJavaConstant().asLong() == 0) { - return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, tool.getMetaAccess()); + return ConstantNode.forConstant(stamp(NodeView.DEFAULT), JavaConstant.NULL_POINTER, tool.getMetaAccess()); } } @@ -124,7 +125,7 @@ public final class WordCastNode extends FixedWithNextNode implements LIRLowerabl @Override public void generate(NodeLIRBuilderTool generator) { Value value = generator.operand(input); - ValueKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp()); + ValueKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); assert kind.getPlatformKind().getSizeInBytes() == value.getPlatformKind().getSizeInBytes(); if (trackedPointer && LIRKind.isValue(kind) && !LIRKind.isValue(value)) { diff --git a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java index 63505988b8e..58b02dc4a77 100644 --- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java +++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java @@ -69,8 +69,10 @@ public class ExpressionResolver implements ExpressionEvaluator { // look it up Monitor m = vm.findByName(id.getName()); if (m == null) { - System.err.println("Warning: Unresolved Symbol: " - + id.getName() + " substituted NaN"); + if (debug) { + System.err.println("Warning: Unresolved Symbol: " + + id.getName() + " substituted NaN"); + } return new Literal(Double.valueOf(Double.NaN)); } if (m.getVariability() == Variability.CONSTANT) { diff --git a/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java index dae6b95c8bf..8d2031f888b 100644 --- a/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java +++ b/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -70,10 +70,8 @@ import javax.net.ssl.TrustManagerFactory; import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; import javax.security.auth.Subject; - import com.sun.jmx.remote.internal.rmi.RMIExporter; import com.sun.jmx.remote.security.JMXPluggableAuthenticator; - import jdk.internal.agent.Agent; import jdk.internal.agent.AgentConfigurationError; import static jdk.internal.agent.AgentConfigurationError.*; @@ -102,6 +100,7 @@ public final class ConnectorBootstrap { public static final String USE_REGISTRY_SSL = "false"; public static final String USE_AUTHENTICATION = "true"; public static final String PASSWORD_FILE_NAME = "jmxremote.password"; + public static final String HASH_PASSWORDS = "true"; public static final String ACCESS_FILE_NAME = "jmxremote.access"; public static final String SSL_NEED_CLIENT_AUTH = "false"; } @@ -129,6 +128,8 @@ public final class ConnectorBootstrap { "com.sun.management.jmxremote.authenticate"; public static final String PASSWORD_FILE_NAME = "com.sun.management.jmxremote.password.file"; + public static final String HASH_PASSWORDS + = "com.sun.management.jmxremote.password.toHashes"; public static final String ACCESS_FILE_NAME = "com.sun.management.jmxremote.access.file"; public static final String LOGIN_CONFIG_NAME = @@ -412,6 +413,7 @@ public final class ConnectorBootstrap { String loginConfigName = null; String passwordFileName = null; + boolean shouldHashPasswords = true; String accessFileName = null; // Initialize settings when authentication is active @@ -426,6 +428,11 @@ public final class ConnectorBootstrap { passwordFileName = props.getProperty(PropertyNames.PASSWORD_FILE_NAME, getDefaultFileName(DefaultValues.PASSWORD_FILE_NAME)); + String hashPasswords + = props.getProperty(PropertyNames.HASH_PASSWORDS, + DefaultValues.HASH_PASSWORDS); + shouldHashPasswords = Boolean.parseBoolean(hashPasswords); + checkPasswordFile(passwordFileName); } @@ -474,7 +481,7 @@ public final class ConnectorBootstrap { sslConfigFileName, enabledCipherSuitesList, enabledProtocolsList, sslNeedClientAuth, useAuthentication, loginConfigName, - passwordFileName, accessFileName, bindAddress, jmxRmiFilter); + passwordFileName, shouldHashPasswords, accessFileName, bindAddress, jmxRmiFilter); cs = data.jmxConnectorServer; url = data.jmxRemoteURL; config("startRemoteConnectorServer", @@ -569,6 +576,10 @@ public final class ConnectorBootstrap { throw new AgentConfigurationError(PASSWORD_FILE_NOT_READABLE, passwordFileName); } + if(!file.canWrite() && PropertyNames.HASH_PASSWORDS.equalsIgnoreCase("true")) { + logger.log(Level.WARNING, ""); + } + FileSystem fs = FileSystem.open(); try { if (fs.supportsFileSecurity(file)) { @@ -729,6 +740,7 @@ public final class ConnectorBootstrap { boolean useAuthentication, String loginConfigName, String passwordFileName, + boolean shouldHashPasswords, String accessFileName, String bindAddress, String jmxRmiFilter) @@ -761,6 +773,9 @@ public final class ConnectorBootstrap { if (passwordFileName != null) { env.put("jmx.remote.x.password.file", passwordFileName); } + if (shouldHashPasswords) { + env.put("jmx.remote.x.password.toHashes", "true"); + } env.put("jmx.remote.x.access.file", accessFileName); diff --git a/src/jdk.management.agent/share/conf/jmxremote.password.template b/src/jdk.management.agent/share/conf/jmxremote.password.template index 13dfd2578bb..c98a0ad253a 100644 --- a/src/jdk.management.agent/share/conf/jmxremote.password.template +++ b/src/jdk.management.agent/share/conf/jmxremote.password.template @@ -3,11 +3,12 @@ # # o Copy this template to jmxremote.password # o Set the user/password entries in jmxremote.password -# o Change the permission of jmxremote.password to read-only -# by the owner. +# o Change the permission of jmxremote.password to be accessible +# only by the owner. +# o The jmxremote.passwords file will be re-written by the server +# to replace all plain text passwords with hashed passwords when +# the file is read by the server. # -# See below for the location of jmxremote.password file. -# ---------------------------------------------------------------------- ############################################################## # Password File for Remote JMX Monitoring @@ -24,41 +25,91 @@ # the management config file $JRE/conf/management/management.properties # or by specifying a system property (See that file for details). - ############################################################## -# File permissions of the jmxremote.password file +# File format of the jmxremote.password file ############################################################## -# Since there are cleartext passwords stored in this file, -# this file must be readable by ONLY the owner, -# otherwise the program will exit with an error. # -# The file format for password and access files is syntactically the same -# as the Properties file format. The syntax is described in the Javadoc -# for java.util.Properties.load. -# Typical password file has multiple lines, where each line is blank, +# The file contains multiple lines where each line is blank, # a comment (like this one), or a password entry. # +# password entry follows the below syntax +# role_name W [clearPassword|hashedPassword] # -# A password entry consists of a role name and an associated -# password. The role name is any string that does not itself contain -# spaces or tabs. The password is again any string that does not -# contain spaces or tabs. Note that passwords appear in the clear in -# this file, so it is a good idea not to use valuable passwords. +# role_name is any string that does not itself contain spaces or tabs. +# W = spaces or tabs +# +# Passwords can be specified via clear text or via a hash. Clear text password +# is any string that does not contain spaces or tabs. Hashed passwords must +# follow the below format. +# hashedPassword = base64_encoded_64_byte_salt W base64_encoded_hash W hash_algorithm +# where, +# base64_encoded_64_byte_salt = 64 byte random salt +# base64_encoded_hash = Hash_algorithm(password + salt) +# W = spaces or tabs +# hash_algorithm = Algorithm string specified using the format below +# https://docs.oracle.com/javase/9/docs/specs/security/standard-names.html#messagedigest-algorithms +# This is an optional field. If not specified, SHA3-512 will be assumed. +# +# If passwords are in clear, they will be overwritten by their hash if all of +# the below criteria are met. +# * com.sun.management.jmxremote.password.toHashes property is set to true in +# management.properties file +# * the password file is writable +# * the system security policy allows writing into the password file, if a +# security manager is configured +# +# In order to change the password for a role, replace the hashed password entry +# with a new clear text password or a new hashed password. If the new password +# is in clear, it will be replaced with its hash when a new login attempt is made. # # A given role should have at most one entry in this file. If a role # has no entry, it has no access. # If multiple entries are found for the same role name, then the last one # is used. # -# In a typical installation, this file can be read by anybody on the +# A user generated hashed password file can also be used instead of clear-text +# password file. If generated by the user, hashed passwords must follow the +# format specified above. +# +# Caution: It is recommended not to edit the password file while the +# agent is running, as edits could be lost if a client connection triggers the +# hashing of the password file at the same time that the file is externally modified. +# The integrity of the file is guaranteed, but any external edits made to the +# file during the short period between the time that the agent reads the file +# and the time that it writes it back might get lost + +############################################################## +# File permissions of the jmxremote.password file +############################################################## +# This file must be made accessible by ONLY the owner, +# otherwise the program will exit with an error. +# +# In a typical installation, this file can be accessed by anybody on the # local machine, and possibly by people on other machines. -# For # security, you should either restrict the access to this file, +# For security, you should either restrict the access to this file except for owner, # or specify another, less accessible file in the management config file # as described above. # -# Following are two commented-out entries. The "measureRole" role has -# password "QED". The "controlRole" role has password "R&D". +# In order to prevent inadverent edits to the password file in the +# production environment, it is recommended to deploy a read-only +# hashed password file. The hashed entries for clear passwords can be generated +# in advance by running the JMX agent. # -# monitorRole QED -# controlRole R&D +############################################################## +# Sample of the jmxremote.password file +############################################################## +# Following are two commented-out entries. The "monitorRole" role has +# password "QED". The "controlRole" role has password "R&D". This is an example +# of specifying passwords in the clear +# +# monitorRole QED +# controlRole R&D +# +# Once a login attempt is made, passwords will be hashed and the file will have +# below entries with clear passwords overwritten by their respective +# SHA3-512 hash +# +# monitorRole trilby APzBTt34rV2l+OMbuvbnOQ4si8UZmfRCVbIY1+fAofV5CkQzXS/FDMGteQQk/R3q1wtt104qImzJEA7gCwl6dw== 4EeTdSJ7X6Imu0Mb+dWqIns7a7QPIBoM3NB/XlpMQSPSicE7PnlALVWn2pBY3Q3pGDHyAb32Hd8GUToQbUhAjA== SHA3-512 +# controlRole roHEJSbRqSSTII4Z4+NOCV2OJaZVQ/dw153Fy2u4ILDP9XiZ426GwzCzc3RtpoqNMwqYIcfdd74xWXSMrWtGaA== w9qDsekgKn0WOVJycDyU0kLBa081zbStcCjUAVEqlfon5Sgx7XHtaodbmzpLegA1jT7Ag36T0zHaEWRHJe2fdA== SHA3-512 +# \ No newline at end of file diff --git a/src/jdk.management.agent/share/conf/management.properties b/src/jdk.management.agent/share/conf/management.properties index 3bf88daf630..1f8d86e1730 100644 --- a/src/jdk.management.agent/share/conf/management.properties +++ b/src/jdk.management.agent/share/conf/management.properties @@ -300,6 +300,17 @@ # For a non-default password file location use the following line # com.sun.management.jmxremote.password.file=filepath +# +# ################# Hash passwords in password file ############## +# com.sun.management.jmxremote.password.toHashes = true|false +# Default for this property is true. +# Specifies if passwords in the password file should be hashed or not. +# If this property is true, and if the password file is writable, and if the +# system security policy allows writing into the password file, +# all the clear passwords in the password file will be replaced by +# their SHA3-512 hash when the file is read by the server +# + # # ################ RMI Access file location ##################### # diff --git a/src/utils/IdealGraphVisualizer/nbproject/platform.properties b/src/utils/IdealGraphVisualizer/nbproject/platform.properties index c86f8f4227d..3e4aeabf98e 100644 --- a/src/utils/IdealGraphVisualizer/nbproject/platform.properties +++ b/src/utils/IdealGraphVisualizer/nbproject/platform.properties @@ -6,7 +6,7 @@ disabled.modules= nbplatform.active.dir=${suite.dir}/nbplatform nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness -bootstrap.url=http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar +bootstrap.url=http://bits.netbeans.org/dev/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar autoupdate.catalog.url=http://updates.netbeans.org/netbeans/updates/7.4/uc/final/distribution/catalog.xml.gz suite.dir=${basedir} nbplatform.active=default diff --git a/src/utils/LogCompilation/Makefile b/src/utils/LogCompilation/Makefile index f04795e44b1..5f9ca083842 100644 --- a/src/utils/LogCompilation/Makefile +++ b/src/utils/LogCompilation/Makefile @@ -25,7 +25,7 @@ PKGLIST = \ com.sun.hotspot.tools.compiler #END PKGLIST -FILELIST = com/sun/hotspot/tools/compiler/*.java +FILELIST = main/java/com/sun/hotspot/tools/compiler/*.java ifneq "x$(ALT_BOOTDIR)" "x" BOOTDIR := $(ALT_BOOTDIR) diff --git a/src/utils/LogCompilation/README b/src/utils/LogCompilation/README index 790173120d6..db9b20aec47 100644 --- a/src/utils/LogCompilation/README +++ b/src/utils/LogCompilation/README @@ -16,3 +16,10 @@ More information about the LogCompilation output can be found at https://wiki.openjdk.java.net/display/HotSpot/LogCompilation+overview https://wiki.openjdk.java.net/display/HotSpot/PrintCompilation https://wiki.openjdk.java.net/display/HotSpot/LogCompilation+tool + +The project layout is now for Maven. To build the project with Maven do: + + mvn clean install + +The build also copies the resulting target jar to ./logc.jar for easy +interop with the Makefile build. \ No newline at end of file diff --git a/src/utils/LogCompilation/pom.xml b/src/utils/LogCompilation/pom.xml new file mode 100644 index 00000000000..ca5c3aa0a1f --- /dev/null +++ b/src/utils/LogCompilation/pom.xml @@ -0,0 +1,110 @@ + + + + 4.0.0 + com.sun.hotspot.tools.compiler + LogCompilation + jar + 1.0-SNAPSHOT + LogCompilation + http://maven.apache.org + + + junit + junit + 4.8.2 + test + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.0 + + + package + + shade + + + + + com.sun.hotspot.tools.compiler.LogCompilation + + + false + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0-M1 + + + maven-antrun-plugin + 1.8 + + + copy + package + + + + + + + run + + + + + + + diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/BasicLogEvent.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/BasicLogEvent.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/CallSite.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/CallSite.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Compilation.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Compilation.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Constants.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Constants.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Constants.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Constants.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCleanupReader.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCleanupReader.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCompilation.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCompilation.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogEvent.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogEvent.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogParser.java similarity index 98% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogParser.java index 04102c2e468..85ce379e16f 100644 --- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java +++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogParser.java @@ -632,7 +632,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler { /** * Entry point for log file parsing with a file reader. - * {@see #parse(String,boolean)} + * {@link #parse(String,boolean)} */ public static ArrayList parse(Reader reader, boolean cleanup) throws Exception { // Create the XML input factory @@ -825,7 +825,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler { * an {@linkplain #site initial scope} with a bogus bytecode index and the * right inline ID, and push the scope with the inline ID attached. Note * that most of late inlining processing happens in - * {@link #endElement()}. + * {@link #endElement(String,String,String)}. *

  • jvms: record a {@linkplain Jvms JVMState}. Depending on the * context in which this event is encountered, this can mean adding * information to the currently being processed trap, lock elimination, or @@ -1025,13 +1025,20 @@ public class LogParser extends DefaultHandler implements ErrorHandler { return; } try { + UncommonTrap unc = new UncommonTrap(Integer.parseInt(search(atts, "bci")), + search(atts, "reason"), + search(atts, "action"), + bytecodes[current_bytecode]); if (scopes.size() == 0) { - reportInternalError("scope underflow"); + // There may be a dangling site not yet in scopes after a late_inline + if (site != null) { + site.add(unc); + } else { + reportInternalError("scope underflow"); + } + } else { + scopes.peek().add(unc); } - scopes.peek().add(new UncommonTrap(Integer.parseInt(search(atts, "bci")), - search(atts, "reason"), - search(atts, "action"), - bytecodes[current_bytecode])); } catch (Error e) { e.printStackTrace(); } @@ -1175,11 +1182,11 @@ public class LogParser extends DefaultHandler implements ErrorHandler { * {@code true} here. (It will be reset when parsing the inlined methods is * done; this happens for the successful case in this method as well, when * {@code parse} elements are processed; and for inlining failures, in - * {@link #startElement()}, when {@code inline_fail} elements are + * {@link #startElement(String,String,String,Attributes)}, when {@code inline_fail} elements are * processed.)
  • *
  • task: perform cleanup at the end of a compilation. Note that * the explicit {@code task_done} event is handled in - * {@link #startElement()}.
  • + * {@link #startElement(String,String,String,Attributes)}. * */ @Override diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Method.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Method.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/NMethod.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/NMethod.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Phase.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Phase.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrap.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrap.java diff --git a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java similarity index 100% rename from src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java rename to src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java diff --git a/test/hotspot/gtest/gc/g1/test_g1HeapVerifier.cpp b/test/hotspot/gtest/gc/g1/test_g1HeapVerifier.cpp new file mode 100644 index 00000000000..9ef0f14f3e6 --- /dev/null +++ b/test/hotspot/gtest/gc/g1/test_g1HeapVerifier.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 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 "gc/g1/g1HeapVerifier.hpp" +#include "logging/logConfiguration.hpp" +#include "unittest.hpp" + +TEST(G1HeapVerifier, parse) { + G1HeapVerifier verifier(NULL); + + LogConfiguration::configure_stdout(LogLevel::Off, true, LOG_TAGS(gc, verify)); + + // Default is to verify everything. + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyAll)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyInitialMark)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyRemark)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyCleanup)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyFull)); + + // Setting one will disable all other. + verifier.parse_verification_type("full"); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyAll)); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly)); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyInitialMark)); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed)); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyRemark)); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyCleanup)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyFull)); + + // Verify case sensitivity. + verifier.parse_verification_type("YOUNG-ONLY"); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly)); + verifier.parse_verification_type("young-only"); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly)); + + // Verify perfect match + verifier.parse_verification_type("mixedgc"); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed)); + verifier.parse_verification_type("mixe"); + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed)); + verifier.parse_verification_type("mixed"); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed)); + + // Verify the last three + verifier.parse_verification_type("initial-mark"); + verifier.parse_verification_type("remark"); + verifier.parse_verification_type("cleanup"); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyRemark)); + ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyCleanup)); + + // Enabling all is not the same as G1VerifyAll + ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyAll)); +} diff --git a/test/hotspot/gtest/logging/test_logMessageTest.cpp b/test/hotspot/gtest/logging/test_logMessageTest.cpp index b3c736f34fa..5540b6c5424 100644 --- a/test/hotspot/gtest/logging/test_logMessageTest.cpp +++ b/test/hotspot/gtest/logging/test_logMessageTest.cpp @@ -27,6 +27,7 @@ #include "logTestUtils.inline.hpp" #include "logging/log.hpp" #include "logging/logMessage.hpp" +#include "memory/allocation.inline.hpp" #include "unittest.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/test/hotspot/jtreg/Makefile b/test/hotspot/jtreg/Makefile index f24c3b081fc..3e4ac3117d4 100644 --- a/test/hotspot/jtreg/Makefile +++ b/test/hotspot/jtreg/Makefile @@ -62,8 +62,12 @@ ifeq ($(findstring CYGWIN,$(UNAME_S)), CYGWIN) endif endif +ifndef CONCURRENCY_FACTOR + CONCURRENCY_FACTOR = 1 +endif + # Concurrency based on min(cores / 2, 12) -CONCURRENCY := $(shell expr $(NUM_CORES) / 2) +CONCURRENCY := $(shell awk 'BEGIN { printf "%.0f", $(NUM_CORES) / 2 * $(CONCURRENCY_FACTOR) }') ifeq ($(CONCURRENCY), 0) CONCURRENCY := 1 else ifeq ($(shell expr $(CONCURRENCY) \> 12), 1) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 76192ac93bd..d1c9d42e0a4 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -76,6 +76,7 @@ runtime/CompressedOops/UseCompressedOops.java 8079353 generic-all # This test is disabled since it will stress NMT and timeout during normal testing runtime/NMT/MallocStressTest.java 8166548 generic-all runtime/SharedArchiveFile/DefaultUseWithClient.java 8154204 generic-all +runtime/AppCDS/UseAppCDS.java 8165603 windows-all ############################################################################# @@ -84,12 +85,7 @@ runtime/SharedArchiveFile/DefaultUseWithClient.java 8154204 generic-all serviceability/jdwp/AllModulesCommandTest.java 8170541 generic-all serviceability/sa/sadebugd/SADebugDTest.java 8163805 generic-all serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/MAAClassFileLoadHook.java 8173936 generic-all -serviceability/sa/JhsdbThreadInfoTest.java 8184042 macosx-all -serviceability/sa/TestInstanceKlassSize.java 8184042 macosx-all -serviceability/sa/TestInstanceKlassSizeForInterface.java 8184042 macosx-all -serviceability/sa/TestPrintMdo.java 8184042 macosx-all serviceability/sa/TestRevPtrsForInvokeDynamic.java 8191270 generic-all -serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java 8184042 macosx-all ############################################################################# # :hotspot_misc diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 69eca8ec107..c7ccaf2f4de 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -53,6 +53,7 @@ requires.properties= \ vm.rtm.os \ vm.aot \ vm.cds \ + vm.cds.custom.loaders \ vm.graal.enabled \ docker.support diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index daf4480f452..d775c50bdb9 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -189,12 +189,27 @@ hotspot_tier1_runtime = \ -runtime/Unsafe/RangeCheck.java \ -runtime/containers/ \ sanity/ \ - testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java + testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java \ + -:hotspot_tier1_runtime_appcds_exclude hotspot_cds = \ runtime/SharedArchiveFile/ \ runtime/CompressedOops/ +# AppCDS +# If modifying AppCDS it is also recommended to run the open hotspot_cds group +hotspot_appcds = \ + runtime/appcds/ + +# A subset of AppCDS tests to be run in JPRT push +hotspot_tier1_runtime_appcds = \ + runtime/appcds/HelloTest.java \ + runtime/appcds/sharedStrings/SharedStringsBasic.java \ + runtime/appcds/ClassLoaderTest.java + +hotspot_tier1_runtime_appcds_exclude = \ + runtime/appcds/ \ + -:hotspot_tier1_runtime_appcds hotspot_tier1_serviceability = \ serviceability/dcmd/compiler \ diff --git a/test/hotspot/jtreg/compiler/loopopts/TestSplitIfPinnedCMove.java b/test/hotspot/jtreg/compiler/loopopts/TestSplitIfPinnedCMove.java new file mode 100644 index 00000000000..bce4fdf28c0 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestSplitIfPinnedCMove.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, 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. + */ + +/** + * @test + * @bug 8191153 + * @summary too strong assert from 8186125 + * + * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestSplitIfPinnedCMove::not_inlined -XX:CompileOnly=TestSplitIfPinnedCMove::test TestSplitIfPinnedCMove + * + */ + +public class TestSplitIfPinnedCMove { + static void not_inlined() {} + + static class A { + A(int f) { + this.f = f; + } + int f; + } + + static int test(int i1, int i3, A a1, A a2) { + // loops to trigger more loop optimization passes + int res = 0; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + res++; + } + } + } + // null check a1 and a2 + res += a1.f + a2.f; + + boolean f2 = false; + if (i1 > 0) { + not_inlined(); + f2 = true; + } + + // Should become CMoveP and be pinned here + res += (i3 > 0 ? a1 : a2).f; + + // f2 should be split through phi with above if + if (f2) { + not_inlined(); + res += 42; + } + + // Another use for i3 > 0 + if (i3 > 0) { + res++; + } + return res; + } + + public static void main(String[] args) { + A a = new A(42); + for (int i = 0; i < 20_000; i++) { + test((i % 2) == 0 ? 0 : 1, (i % 2) == 0 ? 0 : 1, a, a); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/UseCountedLoopSafepointsTest.java b/test/hotspot/jtreg/compiler/loopopts/UseCountedLoopSafepointsTest.java index f23673ad651..e581f4ea3c8 100644 --- a/test/hotspot/jtreg/compiler/loopopts/UseCountedLoopSafepointsTest.java +++ b/test/hotspot/jtreg/compiler/loopopts/UseCountedLoopSafepointsTest.java @@ -61,7 +61,8 @@ public class UseCountedLoopSafepointsTest { OutputAnalyzer oa; try { oa = ProcessTools.executeTestJvm("-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.", - "-XX:" + (enabled ? "+" : "-") + "UseCountedLoopSafepoints", "-XX:+WhiteBoxAPI", + "-XX:" + (enabled ? "+" : "-") + "UseCountedLoopSafepoints", + "-XX:LoopStripMiningIter=" + (enabled ? "1" : "0"), "-XX:+WhiteBoxAPI", "-XX:-Inline", "-Xbatch", "-XX:+PrintIdeal", "-XX:LoopUnrollLimit=0", "-XX:CompileOnly=" + UseCountedLoopSafepoints.class.getName() + "::testMethod", UseCountedLoopSafepoints.class.getName()); diff --git a/test/hotspot/jtreg/compiler/profiling/TestTypeProfiling.java b/test/hotspot/jtreg/compiler/profiling/TestTypeProfiling.java new file mode 100644 index 00000000000..5d41c83d0fa --- /dev/null +++ b/test/hotspot/jtreg/compiler/profiling/TestTypeProfiling.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /** + * @test + * @bug 8189439 + * @summary Parameters type profiling is not performed from aarch64 interpreter + * @requires vm.flavor == "server" & vm.compMode == "Xmixed" & !vm.emulatedClient & !vm.graal.enabled + * @library /test/lib / + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement + * -server -XX:-TieredCompilation -XX:TypeProfileLevel=020 + * compiler.profiling.TestTypeProfiling + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement + * -server -XX:-TieredCompilation -XX:TypeProfileLevel=200 + * compiler.profiling.TestTypeProfiling + */ + +package compiler.profiling; + +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; +import compiler.whitebox.CompilerWhiteBoxTest; +import java.lang.reflect.Method; + +public class TestTypeProfiling { + + public static int[] mParamTypeCheck(Object in) { + try { + return (int[]) in; + } catch (ClassCastException cce) { + return null; + } + } + + static Object x2(Object src) { + return src; + } + + public static int[] mRetTypeCheck(Object in) { + try { + Object out = x2(in); + return (int[]) out; + } catch (ClassCastException cce) { + return null; + } + } + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final int TIERED_STOP_AT_LEVEL = WHITE_BOX.getIntxVMFlag("TieredStopAtLevel").intValue(); + + static boolean deoptimize(Method method, Object src_obj) throws Exception { + for (int i = 0; i < 10; i++) { + method.invoke(null, src_obj); + if (!WHITE_BOX.isMethodCompiled(method)) { + return true; + } + } + return false; + } + + static public void main(String[] args) throws Exception { + if (!Platform.isServer() || Platform.isEmulatedClient()) { + throw new Error("TESTBUG: Not server mode"); + } + // Only execute if C2 is available + if (TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) { + throw new RuntimeException("please enable C2"); + } + + Method method; + if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 20) { + method = TestTypeProfiling.class.getMethod("mRetTypeCheck", Object.class); + } else + if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 200) { + method = TestTypeProfiling.class.getMethod("mParamTypeCheck", Object.class); + } else { + throw new RuntimeException("please setup method return/params type profilation: -XX:TypeProfileLevel=020/200"); + } + + int[] src = new int[10]; + Object src_obj = new Object(); + + // Warm up & make sure we collect type profiling + for (int i = 0; i < 20000; i++) { + mParamTypeCheck(src); + mRetTypeCheck(src); + } + + // And make sure the method is compiled by C2 + WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method.getName() + " is not compiled"); + } + + // should deoptimize for speculative type check + if (!deoptimize(method, src_obj)) { + throw new RuntimeException(method.getName() + " is not deoptimized"); + } + + // compile again + WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method.getName() + " is not recompiled"); + } + + // should deoptimize for actual type check + if (!deoptimize(method, src_obj)) { + throw new RuntimeException(method.getName() + " is not deoptimized (should deoptimize for actual type check)"); + } + + // compile once again + WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method.getName() + " is not recompiled"); + } + + // this time new parameter type should not force deoptimization + if (deoptimize(method, src_obj)) { + throw new RuntimeException(method.getName() + " is deoptimized again"); + } + } +} diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java index cbe0235c4e0..59acd39043e 100644 --- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java +++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java @@ -24,7 +24,8 @@ /* @test * @bug 8167409 - * @run main/othervm/native -Xcomp compiler.runtime.criticalnatives.argumentcorruption.CheckLongArgs + * @requires os.arch != "aarch64" + * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.argumentcorruption.CheckLongArgs */ package compiler.runtime.criticalnatives.argumentcorruption; public class CheckLongArgs { diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java index 17c9a0f9b90..20b7af1726c 100644 --- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java +++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java @@ -24,7 +24,8 @@ /* @test * @bug 8167408 - * @run main/othervm/native -Xcomp compiler.runtime.criticalnatives.lookup.LookUp + * @requires os.arch != "aarch64" + * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.lookup.LookUp */ package compiler.runtime.criticalnatives.lookup; public class LookUp { diff --git a/test/hotspot/jtreg/compiler/unsafe/TestLoopUnswitching.java b/test/hotspot/jtreg/compiler/unsafe/TestLoopUnswitching.java new file mode 100644 index 00000000000..4c35789c718 --- /dev/null +++ b/test/hotspot/jtreg/compiler/unsafe/TestLoopUnswitching.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017, 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. + */ + +/** + * @test + * @bug 8191887 + * @summary loop cloning misses support for Opaque4 node + * @modules java.base/jdk.internal.misc:+open + * + * @run main/othervm -XX:-BackgroundCompilation TestLoopUnswitching + * + */ + +import jdk.internal.misc.Unsafe; +import java.lang.reflect.Field; +import java.util.Arrays; + +public class TestLoopUnswitching { + + static final jdk.internal.misc.Unsafe UNSAFE = Unsafe.getUnsafe(); + static final long F_OFFSET; + + static class A { + int f; + A(int f) { + this.f = f; + } + } + + static { + try { + Field fField = A.class.getDeclaredField("f"); + F_OFFSET = UNSAFE.objectFieldOffset(fField); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + static int test1(A[] arr, boolean flag1, boolean flag2) { + int res = 0; + for (int i = 0; i < 10; i++) { + A a = arr[i]; + if (flag1) { // triggers unswitching + res += UNSAFE.getInt(a, F_OFFSET); + } + if (flag2) { + // Opaque4 node here is in the loop but If is out of the loop + res += UNSAFE.getInt(a, F_OFFSET); + break; + } + res += UNSAFE.getInt(a, F_OFFSET); + } + return res; + } + + static int test2(A[] arr, boolean flag1, boolean flag2) { + int res = 0; + for (int i = 0; i < 10; i++) { + A a = arr[i]; + if (flag1) { // triggers unswitching + res += UNSAFE.getInt(a, F_OFFSET); + } + if (flag2) { + // Opaque4 node here is out of the loop but Bool is in the the loop + res += UNSAFE.getInt(a, F_OFFSET); + break; + } + res += a.f; + } + return res; + } + + static public void main(String[] args) { + A[] arr = new A[1000]; + Arrays.fill(arr, new A(0x42)); + for (int i = 0; i < 20000; i++) { + test1(arr, (i%2) == 0, (i%2) == 0); + test2(arr, (i%2) == 0, (i%2) == 0); + } + } + +} diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAt.java b/test/hotspot/jtreg/gc/TestAllocateHeapAt.java new file mode 100644 index 00000000000..aae999ce1ea --- /dev/null +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAt.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 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 TestAllocateHeapAt.java + * @key gc + * @summary Test to check allocation of Java Heap with AllocateHeapAt option + * @library /test/lib + * @modules java.base/jdk.internal.misc + */ + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import java.util.ArrayList; +import java.util.Collections; + +public class TestAllocateHeapAt { + public static void main(String args[]) throws Exception { + ArrayList vmOpts = new ArrayList(); + + String testVmOptsStr = System.getProperty("test.java.opts"); + if (!testVmOptsStr.isEmpty()) { + String[] testVmOpts = testVmOptsStr.split(" "); + Collections.addAll(vmOpts, testVmOpts); + } + String test_dir = System.getProperty("test.dir", "."); + Collections.addAll(vmOpts, new String[] {"-XX:AllocateHeapAt=" + test_dir, + "-Xlog:gc+heap=info", + "-Xmx32m", + "-Xms32m", + "-version"}); + + System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java")); + for (int i = 0; i < vmOpts.size(); i += 1) { + System.out.print(" " + vmOpts.get(i)); + } + System.out.println(); + + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + System.out.println("Output:\n" + output.getOutput()); + + output.shouldContain("Successfully allocated Java heap at location"); + output.shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java b/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java new file mode 100644 index 00000000000..b7f667c1a17 --- /dev/null +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, 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 TestAllocateHeapAtError.java + * @key gc + * @summary Test to check correct handling of non-existent directory passed to AllocateHeapAt option + * @library /test/lib + * @modules java.base/jdk.internal.misc + */ + +import java.io.File; +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.UUID; + +public class TestAllocateHeapAtError { + public static void main(String args[]) throws Exception { + ArrayList vmOpts = new ArrayList(); + + String testVmOptsStr = System.getProperty("test.java.opts"); + if (!testVmOptsStr.isEmpty()) { + String[] testVmOpts = testVmOptsStr.split(" "); + Collections.addAll(vmOpts, testVmOpts); + } + String test_dir = System.getProperty("test.dir", "."); + + File f = null; + do { + f = new File(test_dir, UUID.randomUUID().toString()); + } while(f.exists()); + + Collections.addAll(vmOpts, new String[] {"-XX:AllocateHeapAt=" + f.getName(), + "-Xlog:gc+heap=info", + "-Xmx32m", + "-Xms32m", + "-version"}); + + System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java")); + for (int i = 0; i < vmOpts.size(); i += 1) { + System.out.print(" " + vmOpts.get(i)); + } + System.out.println(); + + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + System.out.println("Output:\n" + output.getOutput()); + + output.shouldContain("Could not create file for Heap"); + output.shouldContain("Error occurred during initialization of VM"); + output.shouldNotHaveExitValue(0); + } +} + diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java b/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java new file mode 100644 index 00000000000..492a976c1e9 --- /dev/null +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017, 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 TestAllocateHeapAtMultiple.java + * @key gc + * @summary Test to check allocation of Java Heap with AllocateHeapAt option. Has multiple sub-tests to cover different code paths. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @requires vm.bits == "64" + */ + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import java.util.ArrayList; +import java.util.Collections; + +public class TestAllocateHeapAtMultiple { + public static void main(String args[]) throws Exception { + ArrayList vmOpts = new ArrayList(); + String[] testVmOpts = null; + + String test_dir = System.getProperty("test.dir", "."); + + String testVmOptsStr = System.getProperty("test.java.opts"); + if (!testVmOptsStr.isEmpty()) { + testVmOpts = testVmOptsStr.split(" "); + } + + // Extra options for each of the sub-tests + String[] extraOptsList = new String[] { + "-Xmx32m -Xms32m -XX:+UseCompressedOops", // 1. With compressedoops enabled. + "-Xmx32m -Xms32m -XX:-UseCompressedOops", // 2. With compressedoops disabled. + "-Xmx32m -Xms32m -XX:HeapBaseMinAddress=3g", // 3. With user specified HeapBaseMinAddress. + "-Xmx4g -Xms4g", // 4. With larger heap size (UnscaledNarrowOop not possible). + "-Xmx4g -Xms4g -XX:+UseLargePages", // 5. Set UseLargePages. + "-Xmx4g -Xms4g -XX:+UseNUMA" // 6. Set UseNUMA. + }; + + for(String extraOpts : extraOptsList) { + vmOpts.clear(); + if(testVmOpts != null) { + Collections.addAll(vmOpts, testVmOpts); + } + // Add extra options specific to the sub-test. + String[] extraOptsArray = extraOpts.split(" "); + if(extraOptsArray != null) { + Collections.addAll(vmOpts, extraOptsArray); + } + // Add common options + Collections.addAll(vmOpts, new String[] {"-XX:AllocateHeapAt=" + test_dir, + "-Xlog:gc+heap=info", + "-version"}); + + System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java")); + for (int i = 0; i < vmOpts.size(); i += 1) { + System.out.print(" " + vmOpts.get(i)); + } + System.out.println(); + + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + System.out.println("Output:\n" + output.getOutput()); + + output.shouldContain("Successfully allocated Java heap at location"); + output.shouldHaveExitValue(0); + } + } +} diff --git a/test/hotspot/jtreg/gc/TestFullGCALot.java b/test/hotspot/jtreg/gc/TestFullGCALot.java index 19ac9641cd2..90d05f9253b 100644 --- a/test/hotspot/jtreg/gc/TestFullGCALot.java +++ b/test/hotspot/jtreg/gc/TestFullGCALot.java @@ -24,7 +24,7 @@ /* * @test TestFullGCALot * @key gc - * @bug 4187687 + * @bug 4187687 8187819 * @summary Ensure no access violation when using FullGCALot * @requires vm.debug * @run main/othervm -XX:NewSize=10m -XX:+FullGCALot -XX:FullGCALotInterval=120 TestFullGCALot diff --git a/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java b/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java new file mode 100644 index 00000000000..d9b4c94c7fb --- /dev/null +++ b/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.test.lib.Asserts.*; +import gc.testlibrary.PerfCounter; +import gc.testlibrary.PerfCounters; + + +/* @test TestGenerationPerfCounter + * @bug 8080345 + * @requires vm.gc=="null" + * @library /test/lib / + * @summary Tests that the sun.gc.policy.generations returns 2 for all GCs. + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management/sun.management + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run main/othervm -XX:+UsePerfData -XX:+UseSerialGC TestGenerationPerfCounter + * @run main/othervm -XX:+UsePerfData -XX:+UseParallelGC TestGenerationPerfCounter + * @run main/othervm -XX:+UsePerfData -XX:+UseG1GC TestGenerationPerfCounter + * @run main/othervm -XX:+UsePerfData -XX:+UseConcMarkSweepGC TestGenerationPerfCounter + */ +public class TestGenerationPerfCounter { + public static void main(String[] args) throws Exception { + long numGenerations = + PerfCounters.findByName("sun.gc.policy.generations").longValue(); + assertEQ(numGenerations, 2L); + } +} diff --git a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java new file mode 100644 index 00000000000..e923dd4ec1c --- /dev/null +++ b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.List; +import java.util.ArrayList; +import java.lang.management.*; +import static jdk.test.lib.Asserts.*; +import java.util.stream.*; + +/* @test TestMemoryMXBeansAndPoolsPresence + * @bug 8191564 + * @summary Tests that GarbageCollectorMXBeans and GC MemoryPools are created. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @requires vm.gc == null + * @run main/othervm -XX:+UseG1GC TestMemoryMXBeansAndPoolsPresence G1 + * @run main/othervm -XX:+UseConcMarkSweepGC TestMemoryMXBeansAndPoolsPresence CMS + * @run main/othervm -XX:+UseParallelGC TestMemoryMXBeansAndPoolsPresence Parallel + * @run main/othervm -XX:+UseSerialGC TestMemoryMXBeansAndPoolsPresence Serial + */ + +class GCBeanDescription { + public String name; + public String[] poolNames; + + public GCBeanDescription(String name, String[] poolNames) { + this.name = name; + this.poolNames = poolNames; + } +} + +public class TestMemoryMXBeansAndPoolsPresence { + public static void test(GCBeanDescription... expectedBeans) { + List memoryPools = ManagementFactory.getMemoryPoolMXBeans(); + + List gcBeans = ManagementFactory.getGarbageCollectorMXBeans(); + assertEQ(expectedBeans.length, gcBeans.size()); + + for (GCBeanDescription desc : expectedBeans) { + List beans = gcBeans.stream() + .filter(b -> b.getName().equals(desc.name)) + .collect(Collectors.toList()); + assertEQ(beans.size(), 1); + + GarbageCollectorMXBean bean = beans.get(0); + assertEQ(desc.name, bean.getName()); + + String[] pools = bean.getMemoryPoolNames(); + assertEQ(desc.poolNames.length, pools.length); + for (int i = 0; i < desc.poolNames.length; i++) { + assertEQ(desc.poolNames[i], pools[i]); + } + } + } + + public static void main(String[] args) { + switch (args[0]) { + case "G1": + test(new GCBeanDescription("G1 Young Generation", new String[] {"G1 Eden Space", "G1 Survivor Space"}), + new GCBeanDescription("G1 Old Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"})); + break; + case "CMS": + test(new GCBeanDescription("ParNew", new String[] {"Par Eden Space", "Par Survivor Space"}), + new GCBeanDescription("ConcurrentMarkSweep", new String[] {"Par Eden Space", "Par Survivor Space", "CMS Old Gen"})); + break; + case "Parallel": + test(new GCBeanDescription("PS Scavenge", new String[] {"PS Eden Space", "PS Survivor Space"}), + new GCBeanDescription("PS MarkSweep", new String[] {"PS Eden Space", "PS Survivor Space", "PS Old Gen"})); + break; + case "Serial": + test(new GCBeanDescription("Copy", new String[] {"Eden Space", "Survivor Space"}), + new GCBeanDescription("MarkSweepCompact", new String[] {"Eden Space", "Survivor Space", "Tenured Gen"})); + break; + default: + assertTrue(false); + break; + + } + } +} diff --git a/test/hotspot/jtreg/gc/g1/TestInvalidateArrayCopy.java b/test/hotspot/jtreg/gc/g1/TestInvalidateArrayCopy.java new file mode 100644 index 00000000000..38e1e0bddd6 --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestInvalidateArrayCopy.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 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 TestInvalidateArrayCopy + * @bug 8182050 + * @summary Check that benign (0-sized) out of heap bounds card table invalidations do not assert. + * @requires vm.gc.G1 + * @requires vm.debug + * @key gc + * @run main/othervm -XX:NewSize=1M -Xlog:gc -XX:MaxNewSize=1m -XX:-UseTLAB -XX:OldSize=63M -XX:MaxHeapSize=64M TestInvalidateArrayCopy + */ + +// The test allocates zero-sized arrays of j.l.O and tries to arraycopy random data into it so +// that the asserting post barrier calls are executed. It assumes that G1 allocates eden regions +// at the top of the heap for this problem to occur. +public class TestInvalidateArrayCopy { + + static final int NumIterations = 1000000; + + // "Random" source data to "copy" into the target. + static Object[] sourceArray = new Object[10]; + + public static void main(String[] args) { + for (int i = 0; i < NumIterations; i++) { + Object[] x = new Object[0]; + // Make sure that the compiler can't optimize out the above allocations. + if (i % (NumIterations / 10) == 0) { + System.out.println(x); + } + System.arraycopy(sourceArray, 0, x, 0, Math.min(x.length, sourceArray.length)); + } + } +} diff --git a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java new file mode 100644 index 00000000000..35cf30374f9 --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2017, 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 TestVerifyGCType + * @summary Test the VerifyGCType flag to ensure basic functionality. + * @key gc + * @requires vm.gc.G1 + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver TestVerifyGCType + */ + +import java.util.ArrayList; +import java.util.Collections; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import sun.hotspot.WhiteBox; + +public class TestVerifyGCType { + public static final String VERIFY_TAG = "[gc,verify]"; + public static final String VERIFY_BEFORE = "Verifying Before GC"; + public static final String VERIFY_DURING = "Verifying During GC"; + public static final String VERIFY_AFTER = "Verifying After GC"; + + public static void main(String args[]) throws Exception { + testAllVerificationEnabled(); + testAllExplicitlyEnabled(); + testFullAndRemark(); + testConcurrentMark(); + testBadVerificationType(); + testUnsupportedCollector(); + } + + private static void testAllVerificationEnabled() throws Exception { + // Test with all verification enabled + OutputAnalyzer output = testWithVerificationType(new String[0]); + output.shouldHaveExitValue(0); + + verifyCollection("Pause Young", true, false, true, output.getStdout()); + verifyCollection("Pause Initial Mark", true, false, true, output.getStdout()); + verifyCollection("Pause Mixed", true, false, true, output.getStdout()); + verifyCollection("Pause Remark", false, true, false, output.getStdout()); + verifyCollection("Pause Cleanup", false, true, false, output.getStdout()); + verifyCollection("Pause Full", true, true, true, output.getStdout()); + } + + private static void testAllExplicitlyEnabled() throws Exception { + OutputAnalyzer output; + // Test with all explicitly enabled + output = testWithVerificationType(new String[] { + "young-only", "initial-mark", "mixed", "remark", "cleanup", "full"}); + output.shouldHaveExitValue(0); + + verifyCollection("Pause Young", true, false, true, output.getStdout()); + verifyCollection("Pause Initial Mark", true, false, true, output.getStdout()); + verifyCollection("Pause Mixed", true, false, true, output.getStdout()); + verifyCollection("Pause Remark", false, true, false, output.getStdout()); + verifyCollection("Pause Cleanup", false, true, false, output.getStdout()); + verifyCollection("Pause Full", true, true, true, output.getStdout()); + } + + private static void testFullAndRemark() throws Exception { + OutputAnalyzer output; + // Test with full and remark + output = testWithVerificationType(new String[] {"remark", "full"}); + output.shouldHaveExitValue(0); + + verifyCollection("Pause Young", false, false, false, output.getStdout()); + verifyCollection("Pause Initial Mark", false, false, false, output.getStdout()); + verifyCollection("Pause Mixed", false, false, false, output.getStdout()); + verifyCollection("Pause Remark", false, true, false, output.getStdout()); + verifyCollection("Pause Cleanup", false, false, false, output.getStdout()); + verifyCollection("Pause Full", true, true, true, output.getStdout()); + } + + private static void testConcurrentMark() throws Exception { + OutputAnalyzer output; + // Test with full and remark + output = testWithVerificationType(new String[] {"initial-mark", "cleanup", "remark"}); + output.shouldHaveExitValue(0); + + verifyCollection("Pause Young", false, false, false, output.getStdout()); + verifyCollection("Pause Initial Mark", true, false, true, output.getStdout()); + verifyCollection("Pause Mixed", false, false, false, output.getStdout()); + verifyCollection("Pause Remark", false, true, false, output.getStdout()); + verifyCollection("Pause Cleanup", false, true, false, output.getStdout()); + verifyCollection("Pause Full", false, false, false, output.getStdout()); + } + + private static void testBadVerificationType() throws Exception { + OutputAnalyzer output; + // Test bad type + output = testWithVerificationType(new String[] {"old"}); + output.shouldHaveExitValue(0); + + output.shouldMatch("VerifyGCType: '.*' is unknown. Available types are: young-only, initial-mark, mixed, remark, cleanup and full"); + verifyCollection("Pause Young", true, false, true, output.getStdout()); + verifyCollection("Pause Initial Mark", true, false, true, output.getStdout()); + verifyCollection("Pause Mixed", true, false, true, output.getStdout()); + verifyCollection("Pause Remark", false, true, false, output.getStdout()); + verifyCollection("Pause Cleanup", false, true, false, output.getStdout()); + verifyCollection("Pause Full", true, true, true, output.getStdout()); + } + + private static void testUnsupportedCollector() throws Exception { + OutputAnalyzer output; + // Test bad gc + output = testWithBadGC(); + output.shouldHaveExitValue(0); + output.shouldMatch("VerifyGCType is not supported by this collector."); + } + + private static OutputAnalyzer testWithVerificationType(String[] types) throws Exception { + ArrayList basicOpts = new ArrayList<>(); + Collections.addAll(basicOpts, new String[] { + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+UseG1GC", + "-XX:+WhiteBoxAPI", + "-XX:+ExplicitGCInvokesConcurrent", + "-Xlog:gc,gc+start,gc+verify=info", + "-XX:+VerifyBeforeGC", + "-XX:+VerifyAfterGC", + "-XX:+VerifyDuringGC"}); + + for(String verifyType : types) { + basicOpts.add("-XX:VerifyGCType="+verifyType); + } + + basicOpts.add(TriggerGCs.class.getName()); + + ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(basicOpts.toArray( + new String[basicOpts.size()])); + OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + return analyzer; + } + + private static OutputAnalyzer testWithBadGC() throws Exception { + ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(new String[] { + "-XX:+UseParallelGC", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:VerifyGCType=full", + "-version"}); + + OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + return analyzer; + } + + private static void verifyCollection(String name, boolean expectBefore, boolean expectDuring, boolean expectAfter, String data) { + CollectionInfo ci = CollectionInfo.parseFirst(name, data); + Asserts.assertTrue(ci != null, "Expected GC not found: " + name); + + // Verify Before + verifyType(ci, expectBefore, VERIFY_BEFORE); + // Verify During + verifyType(ci, expectDuring, VERIFY_DURING); + // Verify After + verifyType(ci, expectAfter, VERIFY_AFTER); + } + + private static void verifyType(CollectionInfo ci, boolean shouldExist, String pattern) { + if (shouldExist) { + Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification for: " + ci.getName()); + } else { + Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification for: " + ci.getName()); + } + } + + public static class CollectionInfo { + String name; + ArrayList verification; + public CollectionInfo(String name) { + this.name = name; + this.verification = new ArrayList<>(); + System.out.println("Created CollectionInfo: " + name); + } + + public String getName() { + return name; + } + + public void addVerification(String verify) { + System.out.println("Adding: " + verify); + verification.add(verify); + } + + public boolean containsVerification(String contains) { + for (String entry : verification) { + if (entry.contains(contains)) { + return true; + } + } + return false; + } + + static CollectionInfo parseFirst(String name, String data) { + CollectionInfo result = null; + int firstIndex = data.indexOf(name); + if (firstIndex == -1) { + return result; + } + int nextIndex = data.indexOf(name, firstIndex + 1); + if (nextIndex == -1) { + return result; + } + // Found an entry for this name + result = new CollectionInfo(name); + String collectionData = data.substring(firstIndex, nextIndex + name.length()); + for (String line : collectionData.split(System.getProperty("line.separator"))) { + if (line.contains(VERIFY_TAG)) { + result.addVerification(line); + } + } + return result; + } + } + + public static class TriggerGCs { + public static void main(String args[]) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + // Trigger the different GCs using the WhiteBox API and System.gc() + // to start a concurrent cycle with -XX:+ExplicitGCInvokesConcurrent. + wb.fullGC(); // full + System.gc(); // initial-mark, remark and cleanup + // Sleep to make sure concurrent cycle is done + Thread.sleep(1000); + wb.youngGC(); // young-only + wb.youngGC(); // mixed + } + } +} diff --git a/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java b/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java index f648be9f484..24c3bb0e8c8 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java +++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java @@ -32,11 +32,13 @@ import jdk.test.lib.Platform; import sun.management.ManagementFactoryHelper; import static jdk.test.lib.Asserts.*; +import gc.testlibrary.PerfCounter; +import gc.testlibrary.PerfCounters; /* @test TestMetaspacePerfCounters * @bug 8014659 * @requires vm.gc=="null" - * @library /test/lib + * @library /test/lib / * @summary Tests that performance counters for metaspace and compressed class * space exists and works. * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java b/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java index a59e33f7f6a..56d1c002696 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java +++ b/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java @@ -26,10 +26,12 @@ import java.lang.management.*; import jdk.test.lib.Platform; import static jdk.test.lib.Asserts.*; +import gc.testlibrary.PerfCounter; +import gc.testlibrary.PerfCounters; /* @test TestPerfCountersAndMemoryPools * @bug 8023476 - * @library /test/lib + * @library /test/lib / * @requires vm.gc.Serial * @summary Tests that a MemoryPoolMXBeans and PerfCounters for metaspace * report the same data. diff --git a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithAllocateHeapAt.java b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithAllocateHeapAt.java new file mode 100644 index 00000000000..8cd540eb402 --- /dev/null +++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithAllocateHeapAt.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.IOException; + +/* + * @test TestGCBasherWithAllocateHeapAt + * @key gc + * @key stress + * @requires vm.gc.G1 + * @requires vm.flavor == "server" & !vm.emulatedClient + * @summary Stress Java heap allocation with AllocateHeapAt flag using GC basher. + * @run main/othervm/timeout=500 -Xlog:gc*=info -Xmx256m -server -XX:+UseG1GC -XX:AllocateHeapAt=. TestGCBasherWithAllocateHeapAt 120000 + */ +public class TestGCBasherWithAllocateHeapAt { + public static void main(String[] args) throws IOException { + TestGCBasher.main(args); + } +} diff --git a/test/hotspot/jtreg/gc/metaspace/PerfCounter.java b/test/hotspot/jtreg/gc/testlibrary/PerfCounter.java similarity index 98% rename from test/hotspot/jtreg/gc/metaspace/PerfCounter.java rename to test/hotspot/jtreg/gc/testlibrary/PerfCounter.java index d39277c910e..2cafcdfb9fc 100644 --- a/test/hotspot/jtreg/gc/metaspace/PerfCounter.java +++ b/test/hotspot/jtreg/gc/testlibrary/PerfCounter.java @@ -21,6 +21,8 @@ * questions. */ +package gc.testlibrary; + import sun.jvmstat.monitor.Monitor; /** diff --git a/test/hotspot/jtreg/gc/metaspace/PerfCounters.java b/test/hotspot/jtreg/gc/testlibrary/PerfCounters.java similarity index 99% rename from test/hotspot/jtreg/gc/metaspace/PerfCounters.java rename to test/hotspot/jtreg/gc/testlibrary/PerfCounters.java index c1242b1bee5..b6e6a1f1da1 100644 --- a/test/hotspot/jtreg/gc/metaspace/PerfCounters.java +++ b/test/hotspot/jtreg/gc/testlibrary/PerfCounters.java @@ -21,6 +21,8 @@ * questions. */ +package gc.testlibrary; + import sun.jvmstat.monitor.Monitor; import sun.jvmstat.monitor.MonitorException; import sun.jvmstat.monitor.MonitoredHost; diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index 78820042fea..bedcad2e4fe 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -46,6 +46,11 @@ public class VMDeprecatedOptions { {"MinRAMFraction", "2"}, {"InitialRAMFraction", "64"}, {"AssumeMP", "false"}, + {"UseMembar", "true"}, + {"FastTLABRefill", "false"}, + {"DeferPollingPageLoopCount", "-1"}, + {"SafepointSpinBeforeYield", "2000"}, + {"DeferThrSuspendLoopCount", "4000"}, // deprecated alias flags (see also aliased_jvm_flags): {"DefaultMaxRAMFraction", "4"}, diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java b/test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java index 26882f59d61..d820809a791 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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,6 +23,7 @@ /* * @test + * @requires (vm.debug == true) * @bug 6888954 * @bug 8015884 * @summary Exercise HotSpot error handling code by invoking java with @@ -39,6 +40,7 @@ import jdk.test.lib.process.OutputAnalyzer; public class ErrorHandler { public static OutputAnalyzer runTest(int testcase) throws Exception { + // The -XX:ErrorHandlerTest=N option requires debug bits. return new OutputAnalyzer( ProcessTools.createJavaProcessBuilder( "-XX:-TransmitErrorReport", "-XX:-CreateCoredumpOnCrash", "-XX:ErrorHandlerTest=" + testcase) @@ -46,10 +48,6 @@ public class ErrorHandler { } public static void main(String[] args) throws Exception { - // Test is only applicable for debug builds - if (!Platform.isDebugBuild()) { - return; - } // Keep this in sync with hotspot/src/share/vm/utilities/debug.cpp int i = 1; String[] strings = { @@ -69,6 +67,10 @@ public class ErrorHandler { String[] patterns = { "(SIGILL|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc=", "(SIGBUS|SIGSEGV|SIGILL|EXCEPTION_ACCESS_VIOLATION).* at pc=" + // -XX:ErrorHandlerTest=14 is tested by SafeFetchInErrorHandlingTest.java + // -XX:ErrorHandlerTest=15 is tested by SecondaryErrorTest.java + // -XX:ErrorHandlerTest=16 is tested by ThreadsListHandleInErrorHandlingTest.java + // -XX:ErrorHandlerTest=17 is tested by NestedThreadsListHandleInErrorHandlingTest.java }; for (String s : strings) { diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java new file mode 100644 index 00000000000..c0f2e0b7b2b --- /dev/null +++ b/test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.regex.Pattern; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @requires (vm.debug == true) + * @bug 8167108 + * @summary Nested ThreadsListHandle info should be in error handling output. + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableThreadSMRStatistics NestedThreadsListHandleInErrorHandlingTest + */ + +/* + * This test was created using SafeFetchInErrorHandlingTest.java + * as a guide. + */ +public class NestedThreadsListHandleInErrorHandlingTest { + public static void main(String[] args) throws Exception { + + // The -XX:ErrorHandlerTest=N option requires debug bits. + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-Xmx100M", + "-XX:ErrorHandlerTest=17", + "-XX:-CreateCoredumpOnCrash", + "-version"); + + OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); + + // We should have crashed with a specific fatal error: + output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*"); + System.out.println("Found fatal error header."); + output_detail.shouldMatch("# +fatal error: Force crash with a nested ThreadsListHandle."); + System.out.println("Found specific fatal error."); + + // Extract hs_err_pid file. + String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1); + if (hs_err_file == null) { + throw new RuntimeException("Did not find hs_err_pid file in output.\n"); + } + + File f = new File(hs_err_file); + if (!f.exists()) { + throw new RuntimeException("hs_err_pid file missing at " + + f.getAbsolutePath() + ".\n"); + } + + System.out.println("Found hs_err_pid file. Scanning..."); + + FileInputStream fis = new FileInputStream(f); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line = null; + + Pattern [] pattern = new Pattern[] { + // The "Current thread" line should show a hazard ptr and + // a nested hazard ptr: + Pattern.compile("Current thread .* _threads_hazard_ptr=0x[0-9A-Fa-f][0-9A-Fa-f]*, _nested_threads_hazard_ptr_cnt=1, _nested_threads_hazard_ptrs=0x.*"), + // We should have a section of Threads class SMR info: + Pattern.compile("Threads class SMR info:"), + // We should have one nested ThreadsListHandle: + Pattern.compile(".*, _smr_nested_thread_list_max=1"), + // The current thread (marked with '=>') in the threads list + // should show a hazard ptr: + Pattern.compile("=>.* JavaThread \"main\" .*_threads_hazard_ptr=0x[0-9A-Fa-f][0-9A-Fa-f]*, _nested_threads_hazard_ptr_cnt=1, _nested_threads_hazard_ptrs=0x.*"), + }; + int currentPattern = 0; + + String lastLine = null; + while ((line = br.readLine()) != null) { + if (currentPattern < pattern.length) { + if (pattern[currentPattern].matcher(line).matches()) { + System.out.println("Found: " + line + "."); + currentPattern++; + } + } + lastLine = line; + } + br.close(); + + if (currentPattern < pattern.length) { + throw new RuntimeException("hs_err_pid file incomplete (first missing pattern: " + currentPattern + ")"); + } + + if (!lastLine.equals("END.")) { + throw new RuntimeException("hs-err file incomplete (missing END marker.)"); + } else { + System.out.println("End marker found."); + } + + System.out.println("Done scanning hs_err_pid_file."); + System.out.println("PASSED."); + } +} diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java new file mode 100644 index 00000000000..52d9851a5bb --- /dev/null +++ b/test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.regex.Pattern; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @requires (vm.debug == true) + * @bug 8167108 + * @summary ThreadsListHandle info should be in error handling output. + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableThreadSMRStatistics ThreadsListHandleInErrorHandlingTest + */ + +/* + * This test was created using SafeFetchInErrorHandlingTest.java + * as a guide. + */ +public class ThreadsListHandleInErrorHandlingTest { + public static void main(String[] args) throws Exception { + + // The -XX:ErrorHandlerTest=N option requires debug bits. + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-Xmx100M", + "-XX:ErrorHandlerTest=16", + "-XX:-CreateCoredumpOnCrash", + "-version"); + + OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); + + // We should have crashed with a specific fatal error: + output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*"); + System.out.println("Found fatal error header."); + output_detail.shouldMatch("# +fatal error: Force crash with an active ThreadsListHandle."); + System.out.println("Found specific fatal error."); + + // Extract hs_err_pid file. + String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1); + if (hs_err_file == null) { + throw new RuntimeException("Did not find hs_err_pid file in output.\n"); + } + + File f = new File(hs_err_file); + if (!f.exists()) { + throw new RuntimeException("hs_err_pid file missing at " + + f.getAbsolutePath() + ".\n"); + } + + System.out.println("Found hs_err_pid file. Scanning..."); + + FileInputStream fis = new FileInputStream(f); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line = null; + + Pattern [] pattern = new Pattern[] { + // The "Current thread" line should show a hazard ptr: + Pattern.compile("Current thread .* _threads_hazard_ptr=0x.*"), + // We should have a section of Threads class SMR info: + Pattern.compile("Threads class SMR info:"), + // The current thread (marked with '=>') in the threads list + // should show a hazard ptr: + Pattern.compile("=>.* JavaThread \"main\" .*_threads_hazard_ptr=0x.*"), + }; + int currentPattern = 0; + + String lastLine = null; + while ((line = br.readLine()) != null) { + if (currentPattern < pattern.length) { + if (pattern[currentPattern].matcher(line).matches()) { + System.out.println("Found: " + line + "."); + currentPattern++; + } + } + lastLine = line; + } + br.close(); + + if (currentPattern < pattern.length) { + throw new RuntimeException("hs_err_pid file incomplete (first missing pattern: " + currentPattern + ")"); + } + + if (!lastLine.equals("END.")) { + throw new RuntimeException("hs-err file incomplete (missing END marker.)"); + } else { + System.out.println("End marker found."); + } + + System.out.println("Done scanning hs_err_pid_file."); + System.out.println("PASSED."); + } +} diff --git a/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java b/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java index c6614fa4d31..9cf2534d485 100644 --- a/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java +++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java @@ -86,6 +86,9 @@ public class BootAppendTests { logTestCase("5"); testBootAppendClass(); + + logTestCase("6"); + testBootAppendExtraDir(); } private static void logTestCase(String msg) { @@ -241,4 +244,28 @@ public class BootAppendTests { } } } + + // Test #6: This is similar to Test #5. During runtime, an extra dir + // is appended to the bootclasspath. It should not invalidate + // the shared archive. + public static void testBootAppendExtraDir() throws Exception { + for (String mode : modes) { + CDSOptions opts = (new CDSOptions()) + .setXShareMode(mode).setUseVersion(false) + .addPrefix("-Xbootclasspath/a:" + bootAppendJar + File.pathSeparator + appJar, + "-showversion", "--limit-modules=java.base", "-cp", appJar) + .addSuffix("-Xlog:class+load=info", + APP_CLASS, BOOT_APPEND_CLASS_NAME); + + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + CDSTestUtils.checkExec(out, opts, "[class,load] nonjdk.myPackage.MyClass"); + + // If CDS is enabled, the nonjdk.myPackage.MyClass should be loaded + // from the shared archive. + if (mode.equals("on")) { + CDSTestUtils.checkExec(out, opts, + "[class,load] nonjdk.myPackage.MyClass source: shared objects file"); + } + } + } } diff --git a/test/hotspot/jtreg/runtime/Thread/CountStackFramesAtExit.java b/test/hotspot/jtreg/runtime/Thread/CountStackFramesAtExit.java new file mode 100644 index 00000000000..af9f6453836 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/CountStackFramesAtExit.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.countStackFrames() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug CountStackFramesAtExit + */ + +import java.util.concurrent.CountDownLatch; + +public class CountStackFramesAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 1000; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } + + public static void main(String[] args) { + CountStackFramesAtExit threads[] = new CountStackFramesAtExit[N_THREADS]; + + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new CountStackFramesAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // This interrupt() call will break the worker out of + // the exitSyncObj.await() call and the countStackFrames() + // calls will come in during thread exit. + threads[i].interrupt(); + for (; late_count <= N_LATE_CALLS; late_count++) { + try { + threads[i].countStackFrames(); + } catch (IllegalThreadStateException itse) { + // ignore because we expect it + } + + if (!threads[i].isAlive()) { + // Done with Thread.countStackFrames() calls since + // thread is not alive. + break; + } + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.countStackFrames()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.countStackFrames() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].countStackFrames(); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/InterruptAtExit.java b/test/hotspot/jtreg/runtime/Thread/InterruptAtExit.java new file mode 100644 index 00000000000..e230bf4ef61 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/InterruptAtExit.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.interrupt() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug InterruptAtExit + */ + +import java.util.concurrent.CountDownLatch; + +public class InterruptAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 1000; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } + + public static void main(String[] args) { + InterruptAtExit threads[] = new InterruptAtExit[N_THREADS]; + + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new InterruptAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // The first interrupt() call will break the + // worker out of the exitSyncObj.await() call + // and the rest will come in during thread exit. + for (; late_count <= N_LATE_CALLS; late_count++) { + threads[i].interrupt(); + + if (!threads[i].isAlive()) { + // Done with Thread.interrupt() calls since + // thread is not alive. + break; + } + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.interrupt()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.interrupt() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].interrupt(); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/IsInterruptedAtExit.java b/test/hotspot/jtreg/runtime/Thread/IsInterruptedAtExit.java new file mode 100644 index 00000000000..b775636e0a9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/IsInterruptedAtExit.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.isInterrupted() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug IsInterruptedAtExit + */ + +import java.util.concurrent.CountDownLatch; + +public class IsInterruptedAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 2000; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } + + public static void main(String[] args) { + IsInterruptedAtExit threads[] = new IsInterruptedAtExit[N_THREADS]; + + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new IsInterruptedAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // This interrupt() call will break the worker out of + // the exitSyncObj.await() call and the isInterrupted() + // calls will come in during thread exit. + threads[i].interrupt(); + for (; late_count <= N_LATE_CALLS; late_count++) { + threads[i].isInterrupted(); + + if (!threads[i].isAlive()) { + // Done with Thread.isInterrupted() calls since + // thread is not alive. + break; + } + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.isInterrupted()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.isInterrupted() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].isInterrupted(); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/ResumeAtExit.java b/test/hotspot/jtreg/runtime/Thread/ResumeAtExit.java new file mode 100644 index 00000000000..d8a0dbc9f9b --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/ResumeAtExit.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.resume() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug ResumeAtExit + */ + +import java.util.concurrent.CountDownLatch; + +public class ResumeAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 2000; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } + + public static void main(String[] args) { + ResumeAtExit threads[] = new ResumeAtExit[N_THREADS]; + + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new ResumeAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // This interrupt() call will break the worker out + // of the exitSyncObj.await() call and the resume() + // calls will come in during thread exit. + threads[i].interrupt(); + for (; late_count <= N_LATE_CALLS; late_count++) { + threads[i].resume(); + + if (!threads[i].isAlive()) { + // Done with Thread.resume() calls since + // thread is not alive. + break; + } + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.resume()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.resume() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].resume(); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/SetNameAtExit.java b/test/hotspot/jtreg/runtime/Thread/SetNameAtExit.java new file mode 100644 index 00000000000..f6dd8c72cc9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/SetNameAtExit.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.setName() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug SetNameAtExit + */ + +import java.util.concurrent.CountDownLatch; + +public class SetNameAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 1000; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } + + public static void main(String[] args) { + SetNameAtExit threads[] = new SetNameAtExit[N_THREADS]; + + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new SetNameAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // This interrupt() call will break the worker out + // of the exitSyncObj.await() call and the setName() + // calls will come in during thread exit. + threads[i].interrupt(); + for (; late_count <= N_LATE_CALLS; late_count++) { + threads[i].setName("T" + i + "-" + late_count); + + if (!threads[i].isAlive()) { + // Done with Thread.setName() calls since + // thread is not alive. + break; + } + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.setName()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.setName() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].setName("T" + i + "-done"); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/SetPriorityAtExit.java b/test/hotspot/jtreg/runtime/Thread/SetPriorityAtExit.java new file mode 100644 index 00000000000..68589056417 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/SetPriorityAtExit.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.setPriority() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug SetPriorityAtExit + */ + +import java.util.concurrent.CountDownLatch; + +public class SetPriorityAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 2000; + + final static int MIN = java.lang.Thread.MIN_PRIORITY; + final static int NORM = java.lang.Thread.NORM_PRIORITY; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } + + public static void main(String[] args) { + SetPriorityAtExit threads[] = new SetPriorityAtExit[N_THREADS]; + + int prio = MIN; + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new SetPriorityAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // This interrupt() call will break the worker out of + // the exitSyncObj.await() call and the setPriority() + // calls will come in during thread exit. + threads[i].interrupt(); + for (; late_count <= N_LATE_CALLS; late_count++) { + threads[i].setPriority(prio); + if (prio == MIN) { + prio = NORM; + } else { + prio = MIN; + } + + if (!threads[i].isAlive()) { + // Done with Thread.setPriority() calls since + // thread is not alive. + break; + } + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.setPriority()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.setPriority() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].setPriority(prio); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/StopAtExit.java b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java new file mode 100644 index 00000000000..3d4306a2da3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.stop() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug StopAtExit + */ + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class StopAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 1000; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + try { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } catch (ThreadDeath td) { + // ignore because we're testing Thread.stop() which throws it + } catch (NoClassDefFoundError ncdfe) { + // ignore because we're testing Thread.stop() which can cause it + } + } + + public static void main(String[] args) { + StopAtExit threads[] = new StopAtExit[N_THREADS]; + + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new StopAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // This interrupt() call will break the worker out + // of the exitSyncObj.await() call and the stop() + // calls will come in during thread exit. + threads[i].interrupt(); + for (; late_count <= N_LATE_CALLS; late_count++) { + threads[i].stop(); + + if (!threads[i].isAlive()) { + // Done with Thread.stop() calls since + // thread is not alive. + break; + } + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } catch (NoClassDefFoundError ncdfe) { + // Ignore because we're testing Thread.stop() which can + // cause it. Yes, a NoClassDefFoundError that happens + // in a worker thread can subsequently be seen in the + // main thread. + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.stop()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.stop() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].stop(); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java b/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java new file mode 100644 index 00000000000..05c1fb4dd2a --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Stress test java.lang.Thread.suspend() at thread exit. + * @run main/othervm -Xlog:thread+smr=debug SuspendAtExit + */ + +import java.util.concurrent.CountDownLatch; + +public class SuspendAtExit extends Thread { + final static int N_THREADS = 32; + final static int N_LATE_CALLS = 10000; + + public CountDownLatch exitSyncObj = new CountDownLatch(1); + public CountDownLatch startSyncObj = new CountDownLatch(1); + + @Override + public void run() { + // Tell main thread we have started. + startSyncObj.countDown(); + try { + // Wait for main thread to interrupt us so we + // can race to exit. + exitSyncObj.await(); + } catch (InterruptedException e) { + // ignore because we expect one + } + } + + public static void main(String[] args) { + SuspendAtExit threads[] = new SuspendAtExit[N_THREADS]; + + for (int i = 0; i < N_THREADS; i++ ) { + threads[i] = new SuspendAtExit(); + int late_count = 1; + threads[i].start(); + try { + // Wait for the worker thread to get going. + threads[i].startSyncObj.await(); + + // This interrupt() call will break the worker out + // of the exitSyncObj.await() call and the suspend() + // calls will come in during thread exit. + threads[i].interrupt(); + for (; late_count <= N_LATE_CALLS; late_count++) { + threads[i].suspend(); + + if (!threads[i].isAlive()) { + // Done with Thread.suspend() calls since + // thread is not alive. + break; + } + threads[i].resume(); + } + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + + System.out.println("INFO: thread #" + i + ": made " + late_count + + " late calls to java.lang.Thread.suspend()"); + System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" + + N_LATE_CALLS + " value is " + + ((late_count >= N_LATE_CALLS) ? "NOT " : "") + + "large enough to cause a Thread.suspend() " + + "call after thread exit."); + + try { + threads[i].join(); + } catch (InterruptedException e) { + throw new Error("Unexpected: " + e); + } + threads[i].suspend(); + threads[i].resume(); + if (threads[i].isAlive()) { + throw new Error("Expected !Thread.isAlive() after thread #" + + i + " has been join()'ed"); + } + } + + String cmd = System.getProperty("sun.java.command"); + if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) { + // Exit with success in a non-JavaTest environment: + System.exit(0); + } + } +} diff --git a/test/hotspot/jtreg/runtime/Thread/TestThreadDumpSMRInfo.java b/test/hotspot/jtreg/runtime/Thread/TestThreadDumpSMRInfo.java new file mode 100644 index 00000000000..02b673bc299 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/TestThreadDumpSMRInfo.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017, 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 8167108 + * @summary Checks whether jstack reports a "Threads class SMR info" section. + * + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableThreadSMRStatistics TestThreadDumpSMRInfo + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.JDKToolFinder; + +public class TestThreadDumpSMRInfo { + // jstack tends to be closely bound to the VM that we are running + // so use getTestJDKTool() instead of getCompileJDKTool() or even + // getJDKTool() which can fall back to "compile.jdk". + final static String JSTACK = JDKToolFinder.getTestJDKTool("jstack"); + final static String PID = "" + ProcessHandle.current().pid(); + + // Here's a sample "Threads class SMR info" section: + // + // Threads class SMR info: + // _smr_java_thread_list=0x0000000000ce8da0, length=23, elements={ + // 0x000000000043a800, 0x0000000000aee800, 0x0000000000b06800, 0x0000000000b26000, + // 0x0000000000b28800, 0x0000000000b2b000, 0x0000000000b2e000, 0x0000000000b30000, + // 0x0000000000b32800, 0x0000000000b35000, 0x0000000000b3f000, 0x0000000000b41800, + // 0x0000000000b44000, 0x0000000000b46800, 0x0000000000b48800, 0x0000000000b53000, + // 0x0000000000b55800, 0x0000000000b57800, 0x0000000000b5a000, 0x0000000000b5c800, + // 0x0000000000cc8800, 0x0000000000fd9800, 0x0000000000ef4800 + // } + // _smr_java_thread_list_alloc_cnt=24, _smr_java_thread_list_free_cnt=23, _smr_java_thread_list_max=23, _smr_nested_thread_list_max=0 + // _smr_delete_lock_wait_cnt=0, _smr_delete_lock_wait_max=0 + // _smr_to_delete_list_cnt=0, _smr_to_delete_list_max=1 + + final static String HEADER_STR = "Threads class SMR info:"; + + static boolean verbose = false; + + public static void main(String[] args) throws Exception { + if (args.length != 0) { + int arg_i = 0; + if (args[arg_i].equals("-v")) { + verbose = true; + arg_i++; + } + } + + ProcessBuilder pb = new ProcessBuilder(JSTACK, PID); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + if (verbose) { + System.out.println("stdout: " + output.getStdout()); + } + + output.shouldHaveExitValue(0); + System.out.println("INFO: jstack ran successfully."); + + output.shouldContain(HEADER_STR); + System.out.println("INFO: Found: '" + HEADER_STR + "' in jstack output."); + + System.out.println("Test PASSED."); + } + + static void usage() { + System.err.println("Usage: java TestThreadDumpSMRInfo [-v]"); + System.exit(1); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64ThreadFactory.java b/test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java similarity index 61% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64ThreadFactory.java rename to test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java index ee2080de713..6db82a771ab 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64ThreadFactory.java +++ b/test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,24 +21,25 @@ * questions. * */ +import jdk.test.lib.cds.CDSOptions; -package sun.jvm.hotspot.debugger.windbg.ia64; +// This class represents options used for +// during creation of the archive and/or running JVM with archive -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.windbg.*; +public class AppCDSOptions extends CDSOptions { + public String appJar; -public class WindbgIA64ThreadFactory implements WindbgThreadFactory { - private WindbgDebugger debugger; + // Application classes to be archived + public String[] appClasses; - public WindbgIA64ThreadFactory(WindbgDebugger debugger) { - this.debugger = debugger; - } + public AppCDSOptions setAppJar(String appJar) { + this.appJar = appJar; + return this; + } - public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { - return new WindbgIA64Thread(debugger, threadIdentifierAddr); - } + public AppCDSOptions setAppClasses(String[] appClasses) { + this.appClasses = appClasses; + return this; + } - public ThreadProxy createThreadWrapper(long id) { - return new WindbgIA64Thread(debugger, id); - } } diff --git a/test/hotspot/jtreg/runtime/appcds/AppendClasspath.java b/test/hotspot/jtreg/runtime/appcds/AppendClasspath.java new file mode 100644 index 00000000000..a59d1f3753b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/AppendClasspath.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, 2017, 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 At run time, it is OK to append new elements to the classpath that was used at dump time. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @compile test-classes/HelloMore.java + * @run main AppendClasspath + */ + +import java.io.File; +import jdk.test.lib.process.OutputAnalyzer; + +public class AppendClasspath { + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String appJar2 = JarBuilder.build("AppendClasspath_HelloMore", "HelloMore"); + + // Dump an archive with a specified JAR file in -classpath + TestCommon.testDump(appJar, TestCommon.list("Hello")); + + // PASS: 1) runtime with classpath containing the one used in dump time + OutputAnalyzer output = TestCommon.execCommon( + "-cp", appJar + File.pathSeparator + appJar2, + "HelloMore"); + TestCommon.checkExec(output); + + final String errorMessage1 = "Unable to use shared archive"; + final String errorMessage2 = "shared class paths mismatch"; + // FAIL: 2) runtime with classpath different from the one used in dump time + // (runtime has an extra jar file prepended to the class path) + output = TestCommon.execCommon( + "-cp", appJar2 + File.pathSeparator + appJar, + "HelloMore"); + output.shouldContain(errorMessage1); + output.shouldContain(errorMessage2); + output.shouldHaveExitValue(1); + + // FAIL: 3) runtime with classpath part of the one used in dump time + TestCommon.testDump(appJar + File.pathSeparator + appJar2, + TestCommon.list("Hello")); + output = TestCommon.execCommon( + "-cp", appJar2, + "Hello"); + output.shouldContain(errorMessage1); + output.shouldContain(errorMessage2); + output.shouldHaveExitValue(1); + + // FAIL: 4) runtime with same set of jar files in the classpath but + // with different order + output = TestCommon.execCommon( + "-cp", appJar2 + File.pathSeparator + appJar, + "HelloMore"); + output.shouldContain(errorMessage1); + output.shouldContain(errorMessage2); + output.shouldHaveExitValue(1); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java b/test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java new file mode 100644 index 00000000000..4e2bbdbce49 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2014, 2017, 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 bootclasspath mismatch test. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main BootClassPathMismatch + */ + +import jdk.test.lib.process.OutputAnalyzer; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.StandardCopyOption; +import java.nio.file.Paths; + + +public class BootClassPathMismatch { + private static final String mismatchMessage = "shared class paths mismatch"; + + public static void main(String[] args) throws Exception { + JarBuilder.getOrCreateHelloJar(); + copyHelloToNewDir(); + + BootClassPathMismatch test = new BootClassPathMismatch(); + test.testBootClassPathMismatch(); + test.testBootClassPathMismatch2(); + test.testBootClassPathMatch(); + } + + /* Error should be detected if: + * dump time: -Xbootclasspath/a:${testdir}/hello.jar + * run-time : -Xbootclasspath/a:${testdir}/newdir/hello.jar + */ + public void testBootClassPathMismatch() throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String appClasses[] = {"Hello"}; + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, appClasses, "-Xbootclasspath/a:" + appJar); + String testDir = TestCommon.getTestDir("newdir"); + String otherJar = testDir + File.separator + "hello.jar"; + OutputAnalyzer execOutput = TestCommon.exec( + appJar, "-verbose:class", "-Xbootclasspath/a:" + otherJar, "Hello"); + try { + TestCommon.checkExec(execOutput, mismatchMessage); + } catch (java.lang.RuntimeException re) { + String cause = re.getMessage(); + if (!mismatchMessage.equals(cause)) { + throw re; + } + } + } + + /* Error should be detected if: + * dump time: + * run-time : -Xbootclasspath/a:${testdir}/hello.jar + */ + public void testBootClassPathMismatch2() throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String appClasses[] = {"Hello"}; + OutputAnalyzer dumpOutput = TestCommon.dump(appJar, appClasses); + OutputAnalyzer execOutput = TestCommon.exec( + appJar, "-verbose:class", "-Xbootclasspath/a:" + appJar, "Hello"); + try { + TestCommon.checkExec(execOutput, mismatchMessage); + } catch (java.lang.RuntimeException re) { + String cause = re.getMessage(); + if (!mismatchMessage.equals(cause)) { + throw re; + } + } + } + + /* No error if: + * dump time: -Xbootclasspath/a:${testdir}/hello.jar + * run-time : -Xbootclasspath/a:${testdir}/hello.jar + */ + public void testBootClassPathMatch() throws Exception { + String appJar = TestCommon.getTestJar("hello.jar"); + String appClasses[] = {"Hello"}; + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, appClasses, "-Xbootclasspath/a:" + appJar); + OutputAnalyzer execOutput = TestCommon.exec( + appJar, "-verbose:class", + "-Xbootclasspath/a:" + appJar, "Hello"); + TestCommon.checkExec(execOutput, + "[class,load] Hello source: shared objects file"); + } + + private static void copyHelloToNewDir() throws Exception { + String classDir = System.getProperty("test.classes"); + String dstDir = classDir + File.separator + "newdir"; + try { + Files.createDirectory(Paths.get(dstDir)); + } catch (FileAlreadyExistsException e) { } + + Files.copy(Paths.get(classDir, "hello.jar"), + Paths.get(dstDir, "hello.jar"), + StandardCopyOption.REPLACE_EXISTING); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/CaseSensitiveClassPath.java b/test/hotspot/jtreg/runtime/appcds/CaseSensitiveClassPath.java new file mode 100644 index 00000000000..56315c16d64 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/CaseSensitiveClassPath.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, 2017, 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 Test case sensitive aspect of comparing class paths + * between dump time and archive use time + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @requires os.family != "mac" + * @compile test-classes/Hello.java + * @run main CaseSensitiveClassPath + */ + +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + + +// Excluded from running on MAC: a more comprehensive case sensitivity detection +// and fix mechanism is needed, which is planned to be implemented in the future. +public class CaseSensitiveClassPath { + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String appJarUpper = appJar.replace("hello", "Hello"); + + OutputAnalyzer out = TestCommon.dump(appJar, TestCommon.list("Hello")); + TestCommon.checkDump(out); + + Path jarPath = Paths.get(appJar); + Path jarPathUpper = null; + + boolean fileExists = false; + try { + jarPathUpper = Files.createFile(Paths.get(appJarUpper)); + } catch (FileAlreadyExistsException faee) { + fileExists = true; + } + + if (!fileExists) { + try { + Files.copy(jarPath, jarPathUpper, StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + throw new java.lang.RuntimeException( + "Failed copying file from " + appJar + " to " + appJarUpper + ".", e); + } + } else { + jarPathUpper = Paths.get(appJarUpper); + } + + out = TestCommon.exec(appJarUpper, "Hello", "-Xlog:class+path=info", + "-Xlog:cds"); + if (TestCommon.isUnableToMap(out)) + return; + + if (Files.isSameFile(jarPath, jarPathUpper)) { + TestCommon.checkExec(out, "Hello World"); + } else { + out.shouldContain("shared class paths mismatch") + .shouldHaveExitValue(1); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/ClassLoaderTest.java b/test/hotspot/jtreg/runtime/appcds/ClassLoaderTest.java new file mode 100644 index 00000000000..8012a1de39a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ClassLoaderTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, 2017, 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 Initiating and defining classloader test. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @compile test-classes/HelloWB.java + * @compile test-classes/ForNameTest.java + * @compile test-classes/BootClassPathAppendHelper.java + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main ClassLoaderTest + */ + +import java.io.File; +import jdk.test.lib.process.OutputAnalyzer; + +public class ClassLoaderTest { + public static void main(String[] args) throws Exception { + JarBuilder.build(true, "ClassLoaderTest-WhiteBox", "sun/hotspot/WhiteBox"); + JarBuilder.getOrCreateHelloJar(); + JarBuilder.build("ClassLoaderTest-HelloWB", "HelloWB"); + JarBuilder.build("ClassLoaderTest-ForName", "ForNameTest"); + ClassLoaderTest test = new ClassLoaderTest(); + test.testBootLoader(); + test.testDefiningLoader(); + } + + public void testBootLoader() throws Exception { + String appJar = TestCommon.getTestJar("ClassLoaderTest-HelloWB.jar"); + String appClasses[] = {"HelloWB"}; + String whiteBoxJar = TestCommon.getTestJar("ClassLoaderTest-WhiteBox.jar"); + String bootClassPath = "-Xbootclasspath/a:" + appJar + + File.pathSeparator + whiteBoxJar; + + TestCommon.dump(appJar, appClasses, bootClassPath); + + OutputAnalyzer runtimeOutput = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", appJar, bootClassPath, "-Xlog:class+load", "HelloWB"); + + if (!TestCommon.isUnableToMap(runtimeOutput)) { + runtimeOutput.shouldNotContain( + "[class,load] HelloWB source: shared objects file by jdk/internal/misc/ClassLoaders$AppClassLoader"); + runtimeOutput.shouldContain("[class,load] HelloWB source: shared objects file"); + } + } + + public void testDefiningLoader() throws Exception { + // The boot loader should be used to load the class when it's + // on the bootclasspath, regardless who is the initiating classloader. + // In this test case, the AppClassLoader is the initiating classloader. + String helloJar = TestCommon.getTestJar("hello.jar"); + String appJar = helloJar + System.getProperty("path.separator") + + TestCommon.getTestJar("ClassLoaderTest-ForName.jar"); + String whiteBoxJar = TestCommon.getTestJar("ClassLoaderTest-WhiteBox.jar"); + String bootClassPath = "-Xbootclasspath/a:" + helloJar + + File.pathSeparator + whiteBoxJar; + + TestCommon.dump(helloJar, TestCommon.list("Hello"), bootClassPath); + + TestCommon.execCommon("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", appJar, bootClassPath, "-XX:+TraceClassPaths", "ForNameTest"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/ClassPathAttr.java b/test/hotspot/jtreg/runtime/appcds/ClassPathAttr.java new file mode 100644 index 00000000000..d32f7b8f2be --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ClassPathAttr.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, 2017, 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 Class-Path: attribute in MANIFEST file + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @run main ClassPathAttr + */ + +import jdk.test.lib.process.OutputAnalyzer; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.StandardCopyOption; +import java.nio.file.Paths; + + +public class ClassPathAttr { + + public static void main(String[] args) throws Exception { + buildCpAttr("cpattr1", "cpattr1.mf", "CpAttr1", "CpAttr1"); + buildCpAttr("cpattr1_long", "cpattr1_long.mf", "CpAttr1", "CpAttr1"); + buildCpAttr("cpattr2", "cpattr2.mf", "CpAttr2", "CpAttr2"); + buildCpAttr("cpattr3", "cpattr3.mf", "CpAttr3", "CpAttr2", "CpAttr3"); + buildCpAttr("cpattr4", "cpattr4.mf", "CpAttr4", + "CpAttr2", "CpAttr3", "CpAttr4", "CpAttr5"); + buildCpAttr("cpattr5_123456789_223456789_323456789_423456789_523456789_623456789", "cpattr5_extra_long.mf", "CpAttr5", "CpAttr5"); + + for (int i=1; i<=2; i++) { + String jar1 = TestCommon.getTestJar("cpattr1.jar"); + String jar4 = TestCommon.getTestJar("cpattr4.jar"); + if (i == 2) { + // Test case #2 -- same as #1, except we use cpattr1_long.jar, which has a super-long + // Class-Path: attribute. + jar1 = TestCommon.getTestJar("cpattr1_long.jar"); + } + String cp = jar1 + File.pathSeparator + jar4; + + TestCommon.testDump(cp, TestCommon.list("CpAttr1", + "CpAttr2", + "CpAttr3", + "CpAttr4", + "CpAttr5")); + + OutputAnalyzer output = TestCommon.execCommon( + "-cp", cp, + "CpAttr1"); + TestCommon.checkExec(output); + + // Logging test for class+path. + output = TestCommon.execCommon( + "-Xlog:class+path", + "-cp", cp, + "CpAttr1"); + if (!TestCommon.isUnableToMap(output)){ + output.shouldMatch("checking shared classpath entry: .*cpattr2.jar"); + output.shouldMatch("checking shared classpath entry: .*cpattr3.jar"); + } + // Make sure aliased TraceClassPaths still works + output = TestCommon.execCommon( + "-XX:+TraceClassPaths", + "-cp", cp, + "CpAttr1"); + if (!TestCommon.isUnableToMap(output)){ + output.shouldMatch("checking shared classpath entry: .*cpattr2.jar"); + output.shouldMatch("checking shared classpath entry: .*cpattr3.jar"); + } + } + } + + private static void buildCpAttr(String jarName, String manifest, String enclosingClassName, String ...testClassNames) throws Exception { + String jarClassesDir = System.getProperty("test.classes") + File.separator + jarName + "_classes"; + try { Files.createDirectory(Paths.get(jarClassesDir)); } catch (FileAlreadyExistsException e) { } + + JarBuilder.compile(jarClassesDir, System.getProperty("test.src") + File.separator + + "test-classes" + File.separator + enclosingClassName + ".java"); + JarBuilder.buildWithManifest(jarName, manifest, jarClassesDir, testClassNames); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java b/test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java new file mode 100644 index 00000000000..8f1fc68b81b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014, 2017, 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 CommandLineFlagCombo + * AppCDS does not support uncompressed oops + * @requires (vm.gc=="null") & ((vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)) + * @summary Test command line flag combinations that + * could likely affect the behaviour of AppCDS + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main/timeout=240 CommandLineFlagCombo + */ + +import jdk.test.lib.BuildHelper; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +public class CommandLineFlagCombo { + + // shared base address test table + private static final String[] testTable = { + "-XX:+UseG1GC", "-XX:+UseSerialGC", "-XX:+UseParallelGC", "-XX:+UseConcMarkSweepGC", + "-XX:+FlightRecorder", + "-XX:+UseLargePages", // may only take effect on machines with large-pages + "-XX:+UseCompressedClassPointers", + "-XX:+UseCompressedOops", + "-XX:ObjectAlignmentInBytes=16", + "-XX:ObjectAlignmentInBytes=32", + "-XX:ObjectAlignmentInBytes=64" + }; + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String classList[] = {"Hello"}; + + for (String testEntry : testTable) { + System.out.println("CommandLineFlagCombo = " + testEntry); + + if (skipTestCase(testEntry)) + continue; + + OutputAnalyzer dumpOutput; + + if (testEntry.equals("-XX:+FlightRecorder")) { + dumpOutput = TestCommon.dump(appJar, classList, "-XX:+UnlockCommercialFeatures", testEntry); + } else { + dumpOutput = TestCommon.dump(appJar, classList, testEntry); + } + + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput; + if (testEntry.equals("-XX:+FlightRecorder")) { + execOutput = TestCommon.exec(appJar, "-XX:+UnlockCommercialFeatures", testEntry, "Hello"); + } else { + execOutput = TestCommon.exec(appJar, testEntry, "Hello"); + } + TestCommon.checkExec(execOutput, "Hello World"); + } + + for (int i=0; i<2; i++) { + String g1Flag, serialFlag; + + // Interned strings are supported only with G1GC. However, we should not crash if: + // 0: archive has shared strings, but run time doesn't support shared strings + // 1: archive has no shared strings, but run time supports shared strings + + String dump_g1Flag = "-XX:" + (i == 0 ? "+" : "-") + "UseG1GC"; + String run_g1Flag = "-XX:" + (i != 0 ? "+" : "-") + "UseG1GC"; + String dump_serialFlag = "-XX:" + (i != 0 ? "+" : "-") + "UseSerialGC"; + String run_serialFlag = "-XX:" + (i == 0 ? "+" : "-") + "UseSerialGC"; + + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, classList, dump_g1Flag, dump_serialFlag); + + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, run_g1Flag, run_serialFlag, "Hello"); + TestCommon.checkExec(execOutput, "Hello World"); + } + } + + private static boolean skipTestCase(String testEntry) throws Exception { + if (Platform.is32bit()) + { + if (testEntry.equals("-XX:+UseCompressedOops") || + testEntry.equals("-XX:+UseCompressedClassPointers") || + testEntry.contains("ObjectAlignmentInBytes") ) + { + System.out.println("Test case not applicable on 32-bit platforms"); + return true; + } + } + + if (!BuildHelper.isCommercialBuild() && testEntry.equals("-XX:+FlightRecorder")) + { + System.out.println("Test case not applicable on non-commercial builds"); + return true; + } + + return false; + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/CommandLineFlagComboNegative.java b/test/hotspot/jtreg/runtime/appcds/CommandLineFlagComboNegative.java new file mode 100644 index 00000000000..75effb9926c --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/CommandLineFlagComboNegative.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014, 2017, 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 CommandLineFlagComboNegative + * @summary Test command line flag combinations that differ between + * the dump and execute steps, in such way that they cause errors + * E.g. use compressed oops for creating and archive, but then + * execute w/o compressed oops + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main CommandLineFlagComboNegative + */ + +import java.util.ArrayList; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +public class CommandLineFlagComboNegative { + + private class TestVector { + public String testOptionForDumpStep; + public String testOptionForExecuteStep; + public String expectedErrorMsg; + public int expectedErrorCode; + + public TestVector(String testOptionForDumpStep, String testOptionForExecuteStep, + String expectedErrorMsg, int expectedErrorCode) { + this.testOptionForDumpStep=testOptionForDumpStep; + this.testOptionForExecuteStep=testOptionForExecuteStep; + this.expectedErrorMsg=expectedErrorMsg; + this.expectedErrorCode=expectedErrorCode; + } + } + + private ArrayList testTable = new ArrayList(); + + private void initTestTable() { + // These options are not applicable on 32-bit platforms + if (Platform.is64bit()) { + testTable.add( new TestVector("-XX:ObjectAlignmentInBytes=8", "-XX:ObjectAlignmentInBytes=16", + "An error has occurred while processing the shared archive file", 1) ); + testTable.add( new TestVector("-XX:ObjectAlignmentInBytes=64", "-XX:ObjectAlignmentInBytes=32", + "An error has occurred while processing the shared archive file", 1) ); + testTable.add( new TestVector("-XX:+UseCompressedOops", "-XX:-UseCompressedOops", + "Class data sharing is inconsistent with other specified options", 1) ); + testTable.add( new TestVector("-XX:+UseCompressedClassPointers", "-XX:-UseCompressedClassPointers", + "Class data sharing is inconsistent with other specified options", 1) ); + } + } + + private void runTests() throws Exception + { + for (TestVector testEntry : testTable) { + System.out.println("CommandLineFlagComboNegative: dump = " + testEntry.testOptionForDumpStep); + System.out.println("CommandLineFlagComboNegative: execute = " + testEntry.testOptionForExecuteStep); + + String appJar = JarBuilder.getOrCreateHelloJar(); + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, new String[] {"Hello"}, testEntry.testOptionForDumpStep); + + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, testEntry.testOptionForExecuteStep, "Hello"); + execOutput.shouldContain(testEntry.expectedErrorMsg); + execOutput.shouldHaveExitValue(testEntry.expectedErrorCode); + } + } + + public static void main(String[] args) throws Exception { + CommandLineFlagComboNegative thisClass = new CommandLineFlagComboNegative(); + thisClass.initTestTable(); + thisClass.runTests(); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/CompilerUtils.java b/test/hotspot/jtreg/runtime/appcds/CompilerUtils.java new file mode 100644 index 00000000000..cfb5d20ba5c --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/CompilerUtils.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * This class consists exclusively of static utility methods for invoking the + * java compiler. + * + * This class will eventually move to jdk.testlibrary. + */ + +public final class CompilerUtils { + private CompilerUtils() { } + + /** + * Compile all the java sources in {@code /**} to + * {@code /**}. The destination directory will be created if + * it doesn't exist. + * + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @return true if the compilation is successful + * + * @throws IOException if there is an I/O error scanning the source tree or + * creating the destination directory + */ + public static boolean compile(Path source, Path destination, String ... options) + throws IOException + { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); + + List sources + = Files.find(source, Integer.MAX_VALUE, + (file, attrs) -> (file.toString().endsWith(".java"))) + .collect(Collectors.toList()); + + Files.createDirectories(destination); + jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, + Arrays.asList(destination)); + + List opts = Arrays.asList(options); + JavaCompiler.CompilationTask task + = compiler.getTask(null, jfm, null, opts, null, + jfm.getJavaFileObjectsFromPaths(sources)); + + return task.call(); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/DirClasspathTest.java b/test/hotspot/jtreg/runtime/appcds/DirClasspathTest.java new file mode 100644 index 00000000000..047f2d00080 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/DirClasspathTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017, 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 AppCDS handling of directories in -cp + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @run main DirClasspathTest + */ + +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import java.io.File; + +public class DirClasspathTest { + public static void main(String[] args) throws Exception { + File dir = new File(System.getProperty("user.dir")); + File emptydir = new File(dir, "emptydir"); + emptydir.mkdir(); + + // Empty dir in -cp: should be OK + OutputAnalyzer output; + if (!Platform.isWindows()) { + // This block fails on Windows because of JDK-8192927 + output = TestCommon.dump(emptydir.getPath(), TestCommon.list("DoesntMatter"), "-Xlog:class+path=info"); + TestCommon.checkDump(output); + } + + // Non-empty dir in -cp: should fail + // is not empty because it has at least one subdirectory, i.e., + output = TestCommon.dump(dir.getPath(), TestCommon.list("DoesntMatter"), "-Xlog:class+path=info"); + output.shouldNotHaveExitValue(0); + output.shouldContain("CDS allows only empty directories in archived classpaths"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/DumpClassList.java b/test/hotspot/jtreg/runtime/appcds/DumpClassList.java new file mode 100644 index 00000000000..4526770c2da --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/DumpClassList.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016, 2017, 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 DumpLoadedClassList should exclude generated classes, classes in bootclasspath/a and + * --patch-module. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @compile test-classes/ArrayListTest.java + * @run main DumpClassList + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class DumpClassList { + public static void main(String[] args) throws Exception { + // build The app + String[] appClass = new String[] {"ArrayListTest"}; + String classList = "app.list"; + + JarBuilder.build("app", appClass[0]); + String appJar = TestCommon.getTestJar("app.jar"); + + // build patch-module + String source = "package java.lang; " + + "public class NewClass { " + + " static { " + + " System.out.println(\"NewClass\"); "+ + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("java/lang/NewClass", + InMemoryJavaCompiler.compile("java.lang.NewClass", source, "--patch-module=java.base"), + System.getProperty("test.classes")); + + String patchJar = JarBuilder.build("javabase", "java/lang/NewClass"); + + // build bootclasspath/a + String source2 = "package boot.append; " + + "public class Foo { " + + " static { " + + " System.out.println(\"Foo\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("boot/append/Foo", + InMemoryJavaCompiler.compile("boot.append.Foo", source2), + System.getProperty("test.classes")); + + String appendJar = JarBuilder.build("bootappend", "boot/append/Foo"); + + // dump class list + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + true, + "-XX:DumpLoadedClassList=" + classList, + "--patch-module=java.base=" + patchJar, + "-Xbootclasspath/a:" + appendJar, + "-cp", + appJar, + appClass[0]); + OutputAnalyzer output = TestCommon.executeAndLog(pb, "dumpClassList"); + TestCommon.checkExecReturn(output, 0, true, + "hello world", + "skip writing class java/lang/NewClass") // skip classes outside of jrt image + .shouldNotContain("skip writing class boot/append/Foo"); // but classes on -Xbootclasspath/a should not be skipped + + output = TestCommon.createArchive(appJar, appClass, + "-Xbootclasspath/a:" + appendJar, + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:class+load", + "-XX:SharedClassListFile=" + classList); + TestCommon.checkDump(output) + .shouldNotContain("Preload Warning: Cannot find java/lang/invoke/LambdaForm") + .shouldNotContain("Preload Warning: Cannot find boot/append/Foo") + .shouldContain("[info][class,load] boot.append.Foo"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_1.txt b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_1.txt new file mode 100644 index 00000000000..1f4be1af531 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_1.txt @@ -0,0 +1,11 @@ +VERSION: 1.0 +@SECTION: Symbol +0 -1: +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +11 -1 linkMethod +18 -1: type can't be null +20 -1: isAlphaNumericString +43 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Z +1 -1: \t +15 -1: IntCumulateTask +1 -1: \n diff --git a/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_2.txt b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_2.txt new file mode 100644 index 00000000000..f45450da674 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_2.txt @@ -0,0 +1,5 @@ +@SECTION: Symbol +20 -1: isAlphaNumericString +43 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Z +15 -1: IntCumulateTask +1 -1: \n diff --git a/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_3.txt b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_3.txt new file mode 100644 index 00000000000..360e94b24fd --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.invalid_3.txt @@ -0,0 +1,13 @@ +VERSION: 1.0 +@SECTION: Symbol +11 -1: linkMethod +18 -1: isAlphaNumericString +33 -1: java/util/Locale$LocaleNameGetter +23 -1: sun/invoke/util/Wrapper +12 -1: reduceToLong +11 -1: setReadOnly +8 -1: endsWith +55 -1: (Ljava/lang/ClassValue;TT;)V +20 -1: createAnnotationData +6 -1: OfLong +17 -1: getClassSignature diff --git a/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.java b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.java new file mode 100644 index 00000000000..4fc3bb8757e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014, 2017, 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 Adding extra symbols into CDS archive using -XX:SharedArchiveConfigFile + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main ExtraSymbols + */ + +import java.io.*; +import jdk.test.lib.process.OutputAnalyzer; + +public class ExtraSymbols { + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + + // 1. Dump without extra symbols. + OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("Hello")); + checkOutput(output); + int numEntries1 = numOfEntries(output); + + // 2. Dump an archive with extra symbols. All symbols in + // ExtraSymbols.symbols.txt are valid. Dumping should succeed. + output = TestCommon.dump(appJar, TestCommon.list("Hello"), + "-XX:SharedArchiveConfigFile=" + TestCommon.getSourceFile("ExtraSymbols.symbols.txt")); + checkOutput(output); + int numEntries2 = numOfEntries(output); + if (numEntries2 <= numEntries1) { + throw new RuntimeException("No extra symbols added to archive"); + } + output = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(output); + + // 3. Dump with invalid symbol files. Dumping should fail. + String invalid_symbol_files[] = {"ExtraSymbols.invalid_1.txt", + "ExtraSymbols.invalid_2.txt", + "ExtraSymbols.invalid_3.txt"}; + String err_msgs[] = {"Corrupted at line", + "wrong version of hashtable dump file", + "Corrupted at line"}; + for (int i = 0; i < invalid_symbol_files.length; i++) { + output = TestCommon.dump(appJar, TestCommon.list("Hello"), + "-XX:SharedArchiveConfigFile=" + + TestCommon.getSourceFile(invalid_symbol_files[i])); + output.shouldContain("Error occurred during initialization of VM"); + output.shouldContain(err_msgs[i]); + } + } + + static int numOfEntries(OutputAnalyzer output) { + String s = output.firstMatch("Number of entries : .*"); + String subs[] = s.split("[:]"); + int numEntries = Integer.parseInt(subs[1].trim()); + return numEntries; + } + + static void checkOutput(OutputAnalyzer output) throws Exception { + output.shouldContain("Loading classes to share"); + output.shouldContain("Shared symbol table stats -------- base:"); + output.shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.symbols.txt b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.symbols.txt new file mode 100644 index 00000000000..9a75ededb39 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ExtraSymbols.symbols.txt @@ -0,0 +1,10826 @@ +VERSION: 1.0 +@SECTION: Symbol +69 -1: ------------------------------------------------------------123456789 +68 -1: # The values in this file are only used for testing the operation of +63 -1: # adding extra symbols into the CDS archive. None of the values +70 -1: # are interpreted in any way. So even if they contain names of classes +70 -1: # that have been renamed or removed, or string literals that have been +66 -1: # changed or remove from Java source code, it would not affect the +26 -1: # correctness of the test. +0 -1: +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +11 -1: linkMethod +18 -1: type can't be null +20 -1: isAlphaNumericString +43 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Z +72 -1: (Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process; +1 -1: \t +15 -1: IntCumulateTask +1 -1: \n +33 -1: java/util/Locale$LocaleNameGetter +23 -1: sun/invoke/util/Wrapper +57 -1: (Ljava/io/InputStream;Ljava/nio/charset/CharsetDecoder;)V +12 -1: reduceToLong +11 -1: setReadOnly +34 -1: (Ljava/lang/reflect/Executable;)[B +54 -1: ([Ljava/net/URL;Ljava/security/AccessControlContext;)V +15 -1: LegacyMergeSort +8 -1: endsWith +55 -1: (Ljava/lang/ClassValue;TT;)V +20 -1: createAnnotationData +6 -1: OfLong +90 -1: (Ljava/util/Map;)Ljava/util/Map; +1 -1: +17 -1: getClassSignature +1 -1: " +1 -1: # +1 -1: ( +21 -1: MethodHandleImpl.java +10 -1: getUTF8At0 +1 -1: ) +1 -1: * +1 -1: + +1 -1: , +1 -1: - +1 -1: . +18 -1: unsignedEntryNames +1 -1: / +1 -1: 0 +19 -1: java/io/InputStream +38 -1: java/util/concurrent/ThreadLocalRandom +1 -1: : +1 -1: ; +1 -1: < +13 -1: getAndAddLong +1 -1: = +1 -1: > +1 -1: ? +20 -1: getMethodAtIfLoaded0 +1 -1: @ +1 -1: A +7 -1: isAlive +1 -1: B +10 -1: checkIndex +1 -1: C +1 -1: D +1 -1: E +1 -1: F +1 -1: I +30 -1: sun/misc/JavaUtilZipFileAccess +11 -1: classloader +1 -1: J +1 -1: L +14 -1: packageEnabled +8 -1: ([BIII)V +24 -1: Ljava/io/BufferedWriter; +1 -1: S +32 -1: (Ljava/util/function/Consumer;)V +11 -1: refKindName +1 -1: U +1 -1: V +3 1: yyy +18 -1: JavaNetAccess.java +1 -1: Z +7 -1: members +1 -1: [ +1 -1: ] +13 -1: ShortLanguage +1 -1: _ +9 -1: invoke__L +28 -1: (D)Ljava/lang/StringBuilder; +15 -1: isInvokeSpecial +1 -1: c +17 -1: subListRangeCheck +1 -1: e +29 -1: Ljava/security/AllPermission; +27 -1: (C)Ljava/lang/StringBuffer; +28 -1: ([Ljava/lang/Comparable;II)V +50 -1: (Ljava/util/zip/ZipFile;Ljava/util/zip/Inflater;)V +9 -1: invoke__V +1 -1: m +101 -1: (Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/CharsetEncoder;)Lsun/nio/cs/StreamEncoder; +13 -1: MAX_SURROGATE +18 -1: Ljava/lang/String; +21 -1: ensureProtectedAccess +18 -1: getIfModifiedSince +1 -1: r +9 -1: setExtra0 +1 -1: s +47 -1: Ljava/lang/Enum; +1 -1: x +1 -1: { +7 -1: getLast +1 -1: | +1 -1: } +1 -1: ~ +71 -1: (Ljava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +34 -1: (Ljava/nio/charset/Charset;[BII)[C +10 -1: DST_NSHIFT +25 -1: ForEachTransformedKeyTask +26 -1: Ljava/nio/charset/Charset; +56 -1: (Ljava/lang/reflect/Method;)Lsun/reflect/MethodAccessor; +22 -1: StackTraceElement.java +24 -1: sun.zip.zipFile.openTime +27 -1: JNI_COPY_TO_ARRAY_THRESHOLD +26 -1: java/lang/ClassValue$Entry +19 -1: [Ljava/lang/Thread; +56 -1: (Ljava/lang/ClassLoader$NativeLibrary;)Ljava/lang/Class; +7 -1: message +18 -1: parameterToArgSlot +20 -1: [[Ljava/lang/String; +11 -1: bumpVersion +26 -1: Ljava/lang/reflect/Method; +9 -1: getMethod +6 -1: (I)TE; +49 -1: (Ljava/lang/String;)Ljava/lang/invoke/MemberName; +33 -1: sun/misc/URLClassPath$JarLoader$1 +57 -1: (BLjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)V +33 -1: sun/misc/URLClassPath$JarLoader$2 +33 -1: sun/misc/URLClassPath$JarLoader$3 +87 -1: (ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node; +19 -1: FileDescriptor.java +12 -1: forEachValue +36 -1: (Ljava/util/List;)[Ljava/lang/Class; +53 -1: (Ljava/lang/CharSequence;II)Ljava/lang/StringBuilder; +8 -1: hasArray +4 -1: ROWS +10 -1: linkMethod +9 -1: remaining +23 -1: ARRAY_FLOAT_BASE_OFFSET +35 -1: java/lang/reflect/ReflectPermission +24 -1: ()Ljava/net/InetAddress; +7 -1: ngroups +81 -1: Ljava/lang/Object;Ljava/security/PrivilegedExceptionAction;>; +10 -1: putTreeVal +4 -1: list +5 -1: trace +7 -1: blocker +21 -1: reset() not supported +8 -1: JAPANESE +11 -1: PRIVATE_USE +53 -1: (Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodHandle; +32 -1: Invalid JavaFX launch parameters +15 -1: SECONDS_PER_DAY +11 -1: UTF_16.java +24 -1: sun/nio/cs/UTF_8$Encoder +102 -1: (Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;[Ljava/security/Permission;)V +20 -1: (Lsun/misc/Signal;)V +22 -1: MagicAccessorImpl.java +84 -1: (Ljava/lang/String;Ljava/nio/ByteBuffer;Ljava/security/CodeSource;)Ljava/lang/Class; +14 -1: altMetafactory +13 -1: queryOverflow +30 -1: exists, but is not accessible +3 -1: edt +14 -1: MAX_ARRAY_SIZE +20 -1: aliases_UTF_16LE_BOM +34 -1: Ljava/lang/reflect/Constructor<*>; +20 -1: (S)Ljava/lang/Short; +6 -1: STRICT +19 -1: internalCallerClass +27 -1: java/nio/DirectLongBufferRU +13 -1: TIMED_WAITING +15 -1: toGenericString +6 -1: client +10 -1: attachImpl +22 -1: ReflectionFactory.java +8 -1: jsse.jar +37 -1: (IZ)Ljava/lang/AbstractStringBuilder; +41 -1: java/util/LinkedHashMap$LinkedKeyIterator +15 -1: computeIfAbsent +10 -1: GET_TARGET +53 -1: ;>(Ljava/lang/Class;)[TE; +35 -1: java/util/Collections$SingletonList +7 -1: addYear +35 -1: Ljava/lang/Class; +65 -1: (Ljava/util/LinkedHashMap$Entry;Ljava/util/LinkedHashMap$Entry;)V +14 -1: image/x-bitmap +10 -1: (IIII[JI)V +50 -1: (Lsun/misc/URLClassPath$JarLoader;Ljava/net/URL;)V +13 -1: getLineNumber +20 -1: toUpperCaseCharArray +62 -1: (Ljava/util/concurrent/locks/Condition;)Ljava/util/Collection; +11 -1: rotateRight +10 -1: checkPtype +85 -1: (JLjava/util/function/ToLongFunction<-TK;>;JLjava/util/function/LongBinaryOperator;)J +81 -1: (Ljava/lang/Class;Ljava/lang/reflect/Constructor;)Ljava/lang/reflect/Constructor; +15 -1: Illegal style: +28 -1: (Ljava/lang/StringBuilder;)V +41 -1: 1.8.0-internal-iklam_2013_11_27_21_25-b00 +25 -1: Invalid authority field: +55 -1: (Ljava/lang/CharSequence;)Ljava/util/function/Supplier; +12 -1: staticOffset +32 -1: java/util/HashMap$KeySpliterator +13 -1: javaNioAccess +24 -1: (Ljava/util/SortedSet;)V +17 -1: thenComparingLong +2 -1: \n\n +22 -1: registerFieldsToFilter +34 -1: java/lang/invoke/LambdaMetafactory +225 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;Ljava/util/function/BiFunction;Ljava/util/function/BiFunction;)V +26 -1: [[Ljava/lang/CharSequence; +32 -1: java/util/Collections$CheckedMap +147 -1: Ljava/util/AbstractSequentialList;Ljava/util/List;Ljava/util/Deque;Ljava/lang/Cloneable;Ljava/io/Serializable; +204 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; +27 -1: sun/nio/cs/UTF_16BE$Decoder +12 -1: getZoneInfo0 +77 -1: (Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodType; +9 -1: Traverser +35 -1: Ljava/lang/ref/ReferenceQueue; +27 -1: lambda$comparing$ea9a8b3a$1 +7 -1: ([CI)[C +6 -1: getenv +9 -1: newMethod +52 -1: Ljava/lang/reflect/Executable; +164 -1: (Ljava/security/ProtectionDomain;Ljava/security/DomainCombiner;Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;[Ljava/security/Permission;)V +40 -1: (Ljava/lang/String;)Ljava/util/TimeZone; +11 -1: countTokens +202 -1: Ljava/util/concurrent/ConcurrentHashMap$CollectionView;>;Ljava/util/Set;>;Ljava/io/Serializable; +78 -1: (Ljava/util/Collection;)Ljava/util/Collection; +34 -1: (Ljava/lang/reflect/Constructor;)I +15 -1: comparingDouble +24 -1: ()Ljava/util/Collection; +14 -1: invokeFinalize +14 -1: encodeISOArray +77 -1: (Ljava/lang/ref/Reference;Ljava/lang/ref/Reference;)Ljava/lang/ref/Reference; +11 -1: bad index: +34 -1: (Ljava/lang/reflect/Constructor;)V +68 -1: (Ljava/util/jar/JarEntry;Lsun/security/util/ManifestEntryVerifier;)V +53 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;IIIJ)V +27 -1: ([CII)Ljava/nio/CharBuffer; +6 -1: setOut +41 -1: (ILjava/lang/Object;Ljava/lang/Object;I)V +12 -1: MIN_EXPONENT +30 -1: PrivilegedExceptionAction.java +18 -1: key cannot be null +6 -1: CENHDR +73 -1: (ITK;TV;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node; +23 -1: java/lang/reflect/Array +8 -1: AF_LIMIT +2 -1: \r\n +11 -1: getFileName +10 -1: parseShort +22 -1: java/lang/LinkageError +15 -1: FT_LAST_WRAPPER +32 -1: java/util/ArrayDeque$DeqIterator +24 -1: pc-multilingual-850+euro +3 -1: zfc +14 -1: incrementExact +38 -1: (IIII)Lsun/util/calendar/CalendarDate; +8 -1: (II[BI)V +8 -1: isLocked +13 -1: ZoneInfo.java +36 -1: (Lsun/util/calendar/CalendarDate;J)V +35 -1: java/lang/invoke/MethodHandleImpl$1 +31 -1: (Ljava/util/Comparator<-TE;>;)V +19 -1: CharsetEncoder.java +52 -1: ()Ljava/util/Enumeration; +44 -1: (Ljava/io/InputStream;)Ljava/io/InputStream; +7 -1: field +5 -1: abort +25 -1: java/lang/SecurityManager +66 -1: java/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask +1316 -1: \xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe5\xa0\x80\xe4\x80\x8f\xe5\x80\x80\xe4\x80\x8f\xe5\xa0\x80\xe4\x80\x8f\xe6\x80\x80\xe4\x80\x8f\xe5\x80\x80\xe4\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe5\x80\x80\xe4\x80\x8f\xe5\x80\x80\xe4\x80\x8f\xe5\x80\x80\xe4\x80\x8f\xe5\xa0\x80\xe4\x80\x8f\xe6\x80\x80\xe4\x80\x8c\xe6\xa0\x80\x18\xe6\xa0\x80\x18\xe2\xa0\x80\x18\xe2\xa0\x80\xe6\x80\x9a\xe2\xa0\x80\x18\xe6\xa0\x80\x18\xe6\xa0\x80\x18\xee\xa0\x80\x15\xee\xa0\x80\x16\xe6\xa0\x80\x18\xe2\x80\x80\x19\xe3\xa0\x80\x18\xe2\x80\x80\x14\xe3\xa0\x80\x18\xe3\xa0\x80\x18\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe1\xa0\x80\xe3\x98\x89\xe3\xa0\x80\x18\xe6\xa0\x80\x18\xee\xa0\x80\x19\xe6\xa0\x80\x19\xee\xa0\x80\x19\xe6\xa0\x80\x18\xe6\xa0\x80\x18\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xc2\x82\xe7\xbf\xa1\xee\xa0\x80\x15\xe6\xa0\x80\x18\xee\xa0\x80\x16\xe6\xa0\x80\x1b\xe6\xa0\x80\xe5\x80\x97\xe6\xa0\x80\x1b\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xc2\x81\xe7\xbf\xa2\xee\xa0\x80\x15\xe6\xa0\x80\x19\xee\xa0\x80\x16\xe6\xa0\x80\x19\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe5\x80\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe4\xa0\x80\xe1\x80\x8f\xe3\xa0\x80\x0c\xe6\xa0\x80\x18\xe2\xa0\x80\xe6\x80\x9a\xe2\xa0\x80\xe6\x80\x9a\xe2\xa0\x80\xe6\x80\x9a\xe2\xa0\x80\xe6\x80\x9a\xe6\xa0\x80\x1c\xe6\xa0\x80\x18\xe6\xa0\x80\x1b\xe6\xa0\x80\x1c\xc0\x80\xe7\x80\x85\xee\xa0\x80\x1d\xe6\xa0\x80\x19\xe4\xa0\x80\xe1\x80\x90\xe6\xa0\x80\x1c\xe6\xa0\x80\x1b\xe2\xa0\x80\x1c\xe2\xa0\x80\x19\xe1\xa0\x80\xd8\x8b\xe1\xa0\x80\xd8\x8b\xe6\xa0\x80\x1b\xdf\xbd\xe7\x80\x82\xe6\xa0\x80\x18\xe6\xa0\x80\x18\xe6\xa0\x80\x1b\xe1\xa0\x80\xd4\x8b\xc0\x80\xe7\x80\x85\xee\xa0\x80\x1e\xe6\xa0\x80\xe0\xa0\x8b\xe6\xa0\x80\xe0\xa0\x8b\xe6\xa0\x80\xe0\xa0\x8b\xe6\xa0\x80\x18\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xe6\xa0\x80\x19\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xc2\x82\xe7\x80\x81\xdf\xbd\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xe6\xa0\x80\x19\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xc2\x81\xe7\x80\x82\xd8\x9d\xe7\x80\x82 +6 -1: (J[I)I +162 -1: (Ljava/util/List;Ljava/util/Collection;Ljava/util/Locale$FilteringMode;)Ljava/util/List; +21 -1: getQualifiedFieldName +46 -1: Ljava/util/Set;>; +47 -1: (Ljava/util/Collection;Ljava/util/Collection;)Z +10 -1: getRuntime +30 -1: threadLocalRandomSecondarySeed +18 -1: (Ljava/io/File;I)J +10 -1: methodName +34 -1: sun/reflect/generics/tree/TypeTree +35 -1: (Ljava/io/File;)[Ljava/lang/String; +31 -1: java/util/Collections$EmptyList +15 -1: LF_INVINTERFACE +9 -1: notifyAll +18 -1: (Ljava/io/File;I)V +94 -1: (Ljava/lang/String;[BIILjava/security/ProtectionDomain;Ljava/lang/String;)Ljava/lang/Class<*>; +45 -1: (Ljava/lang/String;)Ljava/net/ContentHandler; +3 -1: enc +3 -1: end +18 -1: (Ljava/io/File;I)Z +47 -1: (Ljava/lang/Object;Ljava/lang/reflect/Method;)V +76 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V +19 -1: getURLStreamHandler +46 -1: (Ljava/lang/ClassLoader;Ljava/lang/Class<*>;)V +17 -1: COMPILE_THRESHOLD +15 -1: charset is null +7 -1: ibm-912 +10 -1: basicTypes +7 -1: ibm-914 +78 -1: (Ljava/lang/Class;Ljava/lang/ref/SoftReference;Ljava/lang/ref/SoftReference;)Z +7 -1: ibm-915 +12 -1: JarFileEntry +12 -1: setThreshold +22 -1: (ILjava/lang/Object;)V +55 -1: Ljava/lang/Object; +16 -1: Unknown signal: +3 -1: zip +13 -1: CR_UNMAPPABLE +19 -1: getClassAtIfLoaded0 +21 -1: WindowsClientCounters +29 -1: Ljava/lang/invoke/MethodType; +91 -1: Ljava/util/Collections$UnmodifiableList;Ljava/util/RandomAccess; +23 -1: StackOverflowError.java +13 -1: Launcher.java +9 -1: Signature +7 -1: ibm-920 +153 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;)V +13 -1: setExtensions +26 -1: [Ljava/lang/ref/Reference; +7 -1: ibm-923 +12 -1: BMH.reinvoke +34 -1: java/lang/IllegalArgumentException +53 -1: (Ljava/lang/String;)Ljava/lang/NumberFormatException; +5 -1: .dirs +13 -1: finishToArray +22 -1: (ZI)Ljava/lang/String; +84 -1: (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/RuntimeException; +15 -1: charsetProvider +24 -1: ()Ljava/lang/Class; +10 -1: wordsInUse +26 -1: (Ljava/io/ExpiringCache;)I +53 -1: ()Ljava/util/Iterator;>; +25 -1: com/sun/management/GcInfo +26 -1: getCompatibilityExtensions +69 -1: (Ljava/lang/ref/ReferenceQueue;Ljava/util/concurrent/ConcurrentMap;)V +15 -1: getConstantPool +24 -1: [[Ljava/lang/Comparable; +26 -1: (Ljava/io/ExpiringCache;)V +8 -1: getTable +53 -1: sun/reflect/generics/repository/ConstructorRepository +5 -1: range +36 -1: (Ljava/lang/String;)Ljava/lang/Byte; +72 -1: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V +60 -1: ([TT;TT;Ljava/util/Comparator<-TT;>;)I +20 -1: (Ljava/nio/Bits$1;)V +30 -1: ()Ljava/util/Spliterator; +6 -1: ([BB)I +53 -1: (Ljava/lang/ref/Finalizer;Lsun/misc/JavaLangAccess;)V +11 -1: memberTypes +45 -1: (ILjava/lang/String;)Ljava/lang/StringBuffer; +12 -1: OTHER_SYMBOL +65 -1: (Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType; +43 -1: (Ljava/util/Set;)[Ljava/lang/reflect/Field; +30 -1: (Ljava/lang/ref/Reference$1;)V +18 -1: GREGORIAN_INSTANCE +31 -1: Ljava/lang/FunctionalInterface; +57 -1: (Ljava/lang/Error;Ljava/lang/Exception;)Ljava/lang/Error; +54 -1: ([Ljava/lang/reflect/Field;)[Ljava/lang/reflect/Field; +14 -1: not an array: +6 -1: ([BB)V +9 -1: ISO8859_1 +8 -1: addTrans +27 -1: getFunctionalInterfaceClass +29 -1: lambda$comparingInt$7b0bb60$1 +8 -1: TreeNode +138 -1: Ljava/util/Dictionary;Ljava/util/Map;Ljava/lang/Cloneable;Ljava/io/Serializable; +3 -1: era +22 -1: fakeMethodHandleInvoke +9 -1: addToList +39 -1: (Ljava/lang/Class;[Ljava/lang/String;)V +17 -1: launchApplication +21 -1: randomNumberGenerator +51 -1: Ljava/lang/ThreadLocal;>; +35 -1: java/io/ObjectOutputStream$PutField +42 -1: (ILjava/util/function/IntBinaryOperator;)I +3 -1: err +13 -1: cachedDecoder +32 -1: sun/util/calendar/ZoneInfoFile$1 +23 -1: doIntersectionPrivilege +19 -1: cspc850multilingual +56 -1: Ljava/util/Map;[Ljava/lang/String;>; +11 -1: loader_data +27 -1: (Ljava/util/jar/Manifest;)V +5 -1: files +90 -1: Ljava/util/concurrent/ConcurrentMap; +36 -1: [[Ljava/lang/invoke/LambdaForm$Name; +5 -1: lines +55 -1: (Lsun/misc/URLClassPath$JarLoader;)Lsun/misc/MetaIndex; +9 -1: ansi-1251 +15 -1: refKindIsMethod +29 -1: java/lang/reflect/Constructor +3 -1: est +19 -1: Lsun/misc/Launcher; +109 -1: (Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)TT; +10 -1: getOffsets +9 -1: removeAll +23 -1: java/util/regex/Matcher +8 -1: sumCount +7 -1: implies +10 -1: MAIN_CLASS +75 -1: (Ljava/util/List;)[Ljava/lang/String; +11 -1: getISO3Code +4 -1: high +53 -1: (TK;Ljava/util/function/BiFunction<-TK;-TV;+TV;>;)TV; +17 -1: setNormalizedDate +23 -1: AbstractRepository.java +28 -1: java/util/LinkedList$ListItr +8 -1: isFrozen +38 -1: (Ljava/lang/String;Z)Ljava/lang/Class; +16 -1: ReflectUtil.java +30 -1: ()Ljava/util/stream/IntStream; +57 -1: (Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object; +11 -1: getResource +16 -1: ThreadDeath.java +24 -1: unmodifiableNavigableSet +59 -1: (Ljava/lang/String;)Ljava/util/Enumeration; +24 -1: java.security.auth.debug +58 -1: (Ljava/io/FileInputStream;)Ljava/nio/channels/FileChannel; +25 -1: ()Ljava/util/Enumeration; +11 -1: getInstance +6 -1: MONDAY +15 -1: jdkMinorVersion +16 -1: newThreadWithAcc +6 -1: CENHOW +32 -1: Max. Heap Size (Estimated): +61 -1: (Ljava/lang/invoke/MethodType;Z)Ljava/lang/invoke/LambdaForm; +11 -1: windows-932 +7 -1: Index: +11 -1: composeList +6 -1: utf-16 +6 -1: ibm437 +10 -1: getJarFile +8 -1: , rem = +13 -1: multiNewArray +14 -1: getDefaultPort +39 -1: Ljava/security/cert/CertificateFactory; +10 -1: L_RESERVED +19 -1: getMethodAtIfLoaded +8 -1: needCast +8 -1: IS_FIELD +15 -1: ClassValue.java +31 -1: ()Ljava/util/function/Supplier; +125 -1: (Ljava/lang/Class<*>;)Ljava/util/Map;Ljava/lang/annotation/Annotation;>; +34 -1: lambda$comparingByValue$827a17d5$1 +4 -1: NONE +21 -1: java/nio/DoubleBuffer +33 -1: ()Lsun/reflect/LangReflectAccess; +26 -1: invalid compression method +6 -1: (TK;)Z +16 -1: FT_UNCHECKED_REF +14 -1: getGenericType +17 -1: pathSeparatorChar +8 -1: writeUTF +8 -1: NO_PROXY +188 -1: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V +13 -1: finalRefCount +12 -1: NF_checkCast +6 -1: utf-32 +26 -1: (Ljava/util/ArrayDeque;I)Z +19 -1: prefetchWriteStatic +14 -1: computeInvoker +5 -1: cap= +19 -1: generateCertificate +15 -1: methodModifiers +3 -1: exc +27 -1: ()Lsun/misc/JavaLangAccess; +5 -1: State +14 -1: NullComparator +10 -1: getClassAt +15 -1: printProperties +110 -1: (Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;IILjava/lang/String;[B[B)Ljava/lang/reflect/Constructor; +40 -1: (Ljava/util/List<*>;Ljava/util/Random;)V +63 -1: ()[Ljava/lang/reflect/TypeVariable; +28 -1: (I)Ljava/lang/StringBuilder; +48 -1: ([DIILjava/util/function/DoubleBinaryOperator;)V +3 -1: exp +11 -1: interpret_L +17 -1: Serializable.java +8 -1: FJDouble +12 -1: HashMap.java +9 -1: sys_paths +17 -1: getMainAttributes +14 -1: asDoubleBuffer +10 -1: buildNames +26 -1: TOPLEVEL_WINDOW_PERMISSION +4 -1: Type +31 -1: (Ljava/util/Collection<+TE;>;)V +64 -1: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class<*>; +100 -1: (Ljava/util/Collection;Ljava/lang/Class;)Ljava/util/Collection; +10 -1: checkError +31 -1: (Ljava/util/Collection<+TE;>;)Z +31 -1: java/lang/NoSuchMethodException +6 -1: attach +87 -1: (BLjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; +9 -1: writeChar +44 -1: java/util/ArraysParallelSortHelpers$FJObject +34 -1: (Ljava/lang/Class;Ljava/io/File;)Z +21 -1: java/util/zip/ZipFile +5 -1: dirty +6 -1: (JIZ)V +12 -1: leftoverChar +39 -1: is being loaded in another classloader +10 -1: writeBytes +6 -1: unlink +41 -1: (TT;Ljava/lang/ref/ReferenceQueue;)V +21 -1: getBootstrapResources +95 -1: Ljava/util/AbstractMap;Ljava/io/Serializable; +10 -1: PathStatus +25 -1: java/io/InputStreamReader +15 -1: ISO_8859-9:1989 +37 -1: java/lang/ExceptionInInitializerError +14 -1: exceptionTypes +19 -1: BufferedReader.java +34 -1: Could not create SecurityManager: +13 -1: definePackage +12 -1: getAndAddInt +50 -1: (Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; +30 -1: (Ljava/lang/SecurityManager;)V +12 -1: fxLaunchName +22 -1: BINARYSEARCH_THRESHOLD +29 -1: JVMTI_THREAD_STATE_TERMINATED +9 -1: fullFence +60 -1: (Ljava/lang/String;Z)Ljava/util/Enumeration; +29 -1: java/lang/Thread$WeakClassKey +47 -1: (Ljava/nio/charset/Charset;Ljava/lang/String;)V +8 -1: (TV;)TV; +60 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Object;I)V +47 -1: java/security/cert/CertificateEncodingException +12 -1: BA_DIRECTORY +53 -1: (Ljava/lang/Class;ZLjava/lang/Class;)Ljava/util/List; +9 -1: checkRead +6 -1: +4 -1: args +17 -1: genericMethodType +10 -1: writeFloat +26 -1: Can't handle static method +49 -1: (Ljava/lang/String;)Ljava/lang/invoke/MethodType; +22 -1: MapReduceKeysToIntTask +17 -1: jvm_micro_version +29 -1: (Ljava/util/Map<+TK;+TV;>;Z)V +40 -1: ([Ljava/lang/Object;Ljava/lang/Object;)I +7 -1: vmindex +22 -1: maybeCompileToBytecode +89 -1: Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl; +11 -1: getLauncher +17 -1: jvm_major_version +36 -1: ([IIII)Ljava/util/Spliterator$OfInt; +40 -1: ([Ljava/lang/Object;Ljava/lang/Object;)V +33 -1: IllegalMonitorStateException.java +73 -1: ([ILjava/util/function/IntUnaryOperator;)Ljava/util/function/IntConsumer; +39 -1: (Ljava/lang/String;)Ljava/lang/Package; +29 -1: java/lang/CharacterDataLatin1 +52 -1: (Ljava/lang/annotation/Annotation;)Ljava/lang/Class; +49 -1: (Ljava/lang/CharSequence;II)Ljava/nio/CharBuffer; +53 -1: (Ljava/lang/Object;)Ljava/nio/charset/CharsetDecoder; +22 -1: Ljava/net/FileNameMap; +16 -1: isAnonymousClass +4 -1: item +7 -1: compute +12 -1: user.country +22 -1: malformed context url: +16 -1: jvm_build_number +69 -1: (Ljava/lang/ThreadLocal;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry; +17 -1: getDirectionality +4 -1: save +8 -1: UNMARKED +58 -1: (Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V +12 -1: searchFields +9 -1: frequency +23 -1: getLocalizedInputStream +2 -1: +126 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Object;ILjava/lang/Class<*>;)Ljava/util/List; +39 -1: (Ljava/lang/String;Z)Ljava/lang/String; +7 -1: setZone +2 -1: " +9 -1: checkRef( +11 -1: loadFromXML +49 -1: (Ljava/util/jar/JarFile;Ljava/util/Enumeration;)V +68 -1: (IILsun/util/calendar/CalendarDate;)Lsun/util/calendar/CalendarDate; +2 -1: ( +54 -1: (Ljava/util/TimeZone;)Lsun/util/calendar/CalendarDate; +6 -1: rewind +13 -1: getAndSetLong +30 -1: java/lang/invoke/MethodHandles +11 -1: ListPattern +97 -1: Ljava/util/AbstractList;Ljava/util/RandomAccess;Ljava/io/Serializable; +25 -1: (Ljava/io/InputStream;I)V +9 -1: setMethod +10 -1: H_REG_NAME +39 -1: ([Ljava/lang/Object;)Ljava/lang/Object; +16 -1: AbstractMap.java +68 -1: Ljava/util/Hashtable; +58 -1: (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Process; +23 -1: getFileSystemAttributes +12 -1: toSurrogates +2 -1: !/ +5 -1: empty +24 -1: isUnicodeIdentifierStart +35 -1: sun/nio/cs/StandardCharsets$Classes +27 -1: [Ljava/security/Permission; +13 -1: getDefinition +11 -1: permission= +42 -1: (ILjava/lang/String;)Ljava/nio/ByteBuffer; +69 -1: (Ljava/util/List;>;)Ljava/lang/invoke/MethodType; +3 1: zzz +17 -1: hasLongPrimitives +2 -1: != +13 -1: getInterfaces +2 -1: " +11 -1: noInflation +14 -1: aliases_UTF_16 +2 -1: ") +17 -1: ()Ljava/util/Map; +55 -1: ()Ljava/util/Map; +6 -1: charAt +12 -1: getStringAt0 +10 -1: superClone +28 -1: Ljava/util/AbstractSet; +40 -1: java/lang/ref/Reference$ReferenceHandler +22 -1: NaturalOrderComparator +9 -1: markValue +9 -1: getRegion +26 -1: null permissions parameter +17 -1: Ljava/util/Stack; +14 -1: codebase= +36 -1: (Ljava/util/List;)Ljava/lang/Object; +17 -1: setJavaLangAccess +16 -1: hasQueuedThreads +5 -1: (CC)I +8 -1: toString +5 -1: (CC)J +11 -1: permissions +10 -1: getHeaders +27 -1: java/io/BufferedInputStream +21 -1: unicodelittleunmarked +51 -1: (Ljava/net/URLClassLoader;Ljava/util/Enumeration;)V +14 -1: generateMethod +11 -1: skipForward +55 -1: java/util/concurrent/ConcurrentHashMap$ForEachEntryTask +5 -1: (CC)Z +15 -1: getURLClassPath +84 -1: Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet; +23 -1: primitiveParameterCount +8 -1: security +14 -1: aliases_UTF_32 +22 -1: ()Ljava/util/Set; +9 -1: listFiles +15 -1: insertElementAt +42 -1: Ljava/util/Comparator; +11 -1: getUserInfo +46 -1: ([JIILjava/util/function/LongBinaryOperator;)V +23 -1: (Ljava/util/Iterator;)V +46 -1: ([Ljava/lang/Object;II)Ljava/util/Spliterator; +67 -1: (Ljava/lang/invoke/MemberName;Ljava/lang/Object;)Ljava/lang/Object; +14 -1: normalizeMonth +13 -1: getStackTrace +51 -1: java/lang/invoke/MethodType$ConcurrentWeakInternSet +8 -1: makeChar +2 -1: %% +9 -1: getTarget +21 -1: packageDefinitionLock +52 -1: java/util/concurrent/ConcurrentHashMap$ValueIterator +12 -1: OTHER_NUMBER +22 -1: java/util/jar/JarEntry +11 -1: access$1000 +16 -1: NON_SPACING_MARK +13 -1: last-modified +68 -1: Ljava/lang/Object;Ljava/security/PrivilegedAction; +16 -1: Australia/Darwin +55 -1: (Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;)V +29 -1: Ljava/lang/ref/WeakReference; +19 -1: expungeStaleEntries +41 -1: Ljava/security/PrivilegedActionException; +6 -1: update +23 -1: (Ljava/lang/Object;JB)V +10 -1: newUpdater +39 -1: (Ljava/net/URL;)Ljava/util/jar/JarFile; +25 -1: Ljava/net/ContentHandler; +21 -1: ARRAY_INT_INDEX_SCALE +13 -1: hasSurrogates +27 -1: (Ljava/lang/ThreadGroup;Z)Z +20 -1: createGCNotification +21 -1: negative day of week +11 -1: getInIfOpen +22 -1: java/util/RandomAccess +24 -1: available locales = +21 -1: AccessController.java +44 -1: can not access a protected member of class +4 -1: LONG +15 -1: objectOnlyTypes +75 -1: (Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/CharsetDecoder;)V +14 -1: getFindClasses +10 -1: storeFence +16 -1: asNormalOriginal +45 -1: (Ljava/lang/String;)Ljava/lang/StringBuilder; +6 -1: millis +16 -1: America/St_Johns +38 -1: ()Ljava/lang/IllegalArgumentException; +37 -1: DIRECTIONALITY_POP_DIRECTIONAL_FORMAT +15 -1: implReplaceWith +29 -1: ([C)Ljava/lang/StringBuilder; +15 -1: Appendable.java +41 -1: (Ljava/lang/String;)Ljava/io/InputStream; +26 -1: Illegal Initial Capacity: +9 -1: checkBase +7 -1: setYear +15 -1: DISPLAY_VARIANT +7 -1: getType +31 -1: Ljava/lang/ref/Reference<+TT;>; +15 -1: isFieldOrMethod +35 -1: appendToClassPathForInstrumentation +16 -1: LocaleNameGetter +7 -1: compact +55 -1: ()Ljava/util/Map; +10 -1: dummyQueue +3 -1: ROC +2 -1: (" +15 -1: checkPermission +38 -1: java/util/zip/ZipFile$ZipEntryIterator +8 -1: hexDigit +8 -1: pairs: +2 -1: () +2 -1: )\n +43 -1: handler for url different from this handler +15 -1: isAutoDetecting +37 -1: (Ljava/util/LinkedList$Node;)TE; +11 -1: Unsafe.java +12 -1: windows-1250 +39 -1: java/util/Collections$CheckedCollection +12 -1: windows-1251 +15 -1: codePointAtImpl +12 -1: windows-1252 +12 -1: windows-1253 +12 -1: windows-1254 +58 -1: (Ljava/lang/String;Ljava/lang/Integer;)Ljava/lang/Integer; +5 -1: deref +12 -1: windows-1255 +12 -1: windows-1256 +12 -1: windows-1257 +12 -1: windows-1258 +14 -1: FT_CHECKED_REF +47 -1: (Ljava/util/Hashtable;Ljava/util/Hashtable$1;)V +37 -1: (J)Lsun/util/calendar/Gregorian$Date; +19 -1: checkPropertyAccess +4 -1: file +17 -1: emptyListIterator +26 -1: sun/util/calendar/ZoneInfo +14 -1: file.separator +4 -1: fill +62 -1: (Ljava/util/Spliterator$OfLong;Z)Ljava/util/stream/LongStream; +18 -1: java/util/Iterator +20 -1: reduceValuesToDouble +12 -1: LF_CS_LINKER +26 -1: java/util/Arrays$ArrayList +45 -1: Ljava/util/concurrent/ConcurrentHashMap$Node; +6 -1: skipLF +2 -1: )= +39 -1: (I[Ljava/lang/invoke/LambdaForm$Name;)I +90 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;Ljava/lang/invoke/MemberName;)V +18 -1: parameterModifiers +31 -1: (Ljava/util/Collection<+TK;>;)Z +21 -1: proxy can not be null +22 -1: java/io/FileDescriptor +6 -1: Loader +21 -1: numberOfTrailingZeros +10 -1: addMapping +39 -1: (I[Ljava/lang/invoke/LambdaForm$Name;)Z +30 -1: java/util/Locale$LanguageRange +20 -1: getReflectionFactory +16 -1: shouldMeterInput +56 -1: ([Ljava/lang/reflect/Method;)[Ljava/lang/reflect/Method; +23 -1: sun/net/ProgressMonitor +510 -1: \xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\x01\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\x01\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80\xc0\x80 +28 -1: java/util/Spliterator$OfLong +24 -1: SynchronizedNavigableMap +4 -1: find +6 -1: unsafe +31 -1: java/nio/ByteBufferAsIntBufferB +2 -1: ,\n +6 -1: [ call +14 -1: registerFilter +10 -1: ValuesView +9 -1: untreeify +59 -1: ([Ljava/lang/Object;IILjava/util/function/BinaryOperator;)V +13 -1: getSimpleName +41 -1: (Ljava/util/Vector;Ljava/util/Vector$1;)V +31 -1: java/nio/ByteBufferAsIntBufferL +45 -1: (Ljava/lang/reflect/Field;)Ljava/lang/Object; +13 -1: getDefaultRef +18 -1: mapAlternativeName +30 -1: setDefaultAllowUserInteraction +13 -1: cannotCastMsg +4 -1: )=>{ +7 -1: println +2 -1: , +70 -1: (Ljava/nio/Buffer;IILjava/nio/Buffer;II)Ljava/nio/charset/CoderResult; +32 -1: (ILjava/util/Collection<+TE;>;)Z +9 -1: interpret +104 -1: (Ljava/util/NavigableSet;Ljava/lang/Class;)Ljava/util/NavigableSet; +7 -1: advance +86 -1: Ljava/lang/Object;Ljava/security/PrivilegedExceptionAction; +11 -1: Stack trace +6 -1: raise0 +68 -1: ()Ljava/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap; +32 -1: sun/util/calendar/Gregorian$Date +33 -1: java/lang/ref/ReferenceQueue$Lock +19 -1: constructorAccessor +6 -1: IBM367 +18 -1: CharacterData.java +8 -1: parseURL +32 -1: java/io/FilePermissionCollection +7 -1: ([JI)[J +9 -1: JIS_X0201 +2 -1: -1 +8 -1: encoding +63 -1: ([Ljava/util/WeakHashMap$Entry;[Ljava/util/WeakHashMap$Entry;)V +9 -1: localhost +66 -1: (Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal$1;)V +54 -1: (II[Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +67 -1: (Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; +14 -1: containsAllPDs +23 -1: setAllowUserInteraction +30 -1: Ljava/security/DomainCombiner; +26 -1: Ljava/security/Permission; +30 -1: serializePropertiesToByteArray +112 -1: (Ljava/util/Iterator;Ljava/util/Map;)V +2 -1: .. +6 -1: LOCEXT +2 -1: ./ +26 -1: (Ljava/nio/ByteBuffer;II)V +18 -1: (Ljava/io/File;J)Z +45 -1: (Ljava/lang/StringBuffer;Ljava/lang/String;)V +17 -1: asCollectorChecks +7 -1: actions +5 -1: ([I)I +20 -1: asChange_otherthread +20 -1: forInputStreamReader +69 -1: java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject +5 -1: FINAL +17 -1: staticPermissions +44 -1: (Ljava/lang/Object;)Ljava/lang/StringBuffer; +5 -1: ([I)V +4 -1: swap +10 -1: readOffset +2 -1: /* +112 -1: (JLjava/util/function/Function<-TK;+TU;>;Ljava/util/function/BiFunction<-TU;-TU;+TU;>;)TU; +12 -1: isAsciiDigit +2 -1: /- +2 -1: /. +2 -1: // +5 -1: zones +37 -1: (ILjava/lang/Object;)Ljava/util/List; +17 -1: SHUFFLE_THRESHOLD +32 -1: java/lang/CharacterDataUndefined +23 -1: sun.reflect.noInflation +11 -1: Can not set +36 -1: (Ljava/util/Properties$LineReader;)V +9 -1: debugName +78 -1: (Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode; +6 -1: (III)J +58 -1: (Ljava/util/List;Ljava/util/Collection;)Ljava/lang/String; +19 -1: BufferedWriter.java +148 -1: (Ljava/lang/Class;[Ljava/lang/Class<*>;[Ljava/lang/Class<*>;IILjava/lang/String;[B[B)Ljava/lang/reflect/Constructor; +6 -1: printf +7 -1: signers +2 -1: 0. +4 -1: Date +15 -1: findReplacement +6 -1: (III)V +32 -1: java/nio/ReadOnlyBufferException +92 -1: ([Ljava/lang/String;)Ljava/util/Map;>; +6 -1: (III)Z +43 -1: (Ljava/lang/ClassValue;Ljava/lang/Object;)V +32 -1: java/nio/ByteBufferAsLongBufferB +16 -1: Constructor.java +10 -1: removeLast +9 -1: ([CII[B)I +40 -1: ()Ljava/util/List;>; +2 -1: 1. +7 -1: VARARGS +32 -1: java/nio/ByteBufferAsLongBufferL +18 -1: java/lang/Shutdown +40 -1: not supported, using ISO-8859-1 instead +40 -1: Ljava/util/Collections$EmptyEnumeration; +146 -1: (Ljava/util/SortedMap;Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/SortedMap; +20 -1: aliases_UTF_32LE_BOM +23 -1: getEnclosingConstructor +2 -1: 0X +11 -1: NO_TIMEZONE +37 -1: ()Lsun/misc/JavaNioAccess$BufferPool; +18 -1: printXUsageMessage +9 -1: isPrivate +63 -1: (Ljava/lang/invoke/MemberName;Ljava/lang/invoke/MethodHandle;)V +17 -1: maxSkipBufferSize +76 -1: (Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/CharsetEncoder;)V +40 -1: (Ljava/lang/String;II)Ljava/lang/String; +17 -1: selectAlternative +53 -1: [Ljava/util/concurrent/ConcurrentHashMap$CounterCell; +87 -1: (Ljava/util/function/Supplier<+TS;>;)Ljava/lang/ThreadLocal; +40 -1: Ljava/util/concurrent/ConcurrentHashMap; +41 -1: (Ljava/lang/Character;)Ljava/lang/String; +19 -1: getMemberRefInfoAt0 +14 -1: reduceToDouble +18 -1: SUPPRESSED_CAPTION +6 -1: CANADA +64 -1: (IZ[Ljava/lang/Class<*>;[Ljava/lang/Class<*>;)Ljava/lang/String; +12 -1: UnicodeBlock +2 -1: 0x +44 -1: (Ljava/lang/CharSequence;II)Ljava/io/Writer; +23 -1: getPermissionCollection +19 -1: threadLocalHashCode +9 -1: createMap +25 -1: checkForSpecialAttributes +12 -1: Mark invalid +36 -1: java/lang/CharSequence$1CharIterator +11 -1: local time +16 -1: Enumeration.java +27 -1: (Ljava/util/zip/ZipEntry;)V +11 -1: MATH_SYMBOL +8 -1: filename +24 -1: (Ljava/util/List<*>;II)V +9 -1: bindCache +18 -1: java/io/FileFilter +12 -1: checkInvoker +18 -1: OSEnvironment.java +8 -1: EmptyMap +11 -1: getIterator +35 -1: java/util/function/IntUnaryOperator +35 -1: java/util/WeakHashMap$EntryIterator +90 -1: (Ljava/util/Queue;Ljava/lang/Class;)Ljava/util/Queue; +8 -1: batchFor +16 -1: isValidCodePoint +27 -1: ([Lsun/util/calendar/Era;)V +16 -1: ThreadGroup.java +33 2: sun/net/www/protocol/file/Handler +7 -1: isField +22 -1: sun/misc/OSEnvironment +38 -1: Ljava/lang/Class; +12 -1: ADDRESS_SIZE +8 -1: forDigit +49 -1: (Ljava/lang/Object;)Ljava/util/WeakHashMap$Entry; +13 -1: getCodeSource +41 -1: ([Ljava/lang/Class<*>;)Ljava/lang/String; +39 -1: (Ljava/util/function/Predicate<-TE;>;)Z +13 -1: asFloatBuffer +34 -1: ()Lsun/reflect/generics/tree/Tree; +3 -1: ftp +18 -1: maybeReBoxElements +82 -1: ([BLsun/reflect/ConstantPool;Ljava/lang/Class;)[[Ljava/lang/annotation/Annotation; +48 -1: ()Ljava/util/Set;>; +27 -1: (Ljava/util/NavigableMap;)V +18 -1: parameterSlotCount +20 -1: NF_getCallSiteTarget +16 -1: aliases_US_ASCII +13 -1: NF_staticBase +31 -1: sun/reflect/ConstructorAccessor +26 -1: guessContentTypeFromStream +10 -1: Deprecated +35 -1: System initialization has completed +11 -1: initialized +7 -1: compare +15 -1: maxDirectMemory +19 -1: setLastModifiedTime +7 -1: (J[BZ)J +12 -1: readEpochSec +66 -1: (Ljava/lang/String;Ljava/lang/String;)Lsun/util/locale/BaseLocale; +69 -1: ()Lsun/misc/JavaSecurityProtectionDomainAccess$ProtectionDomainCache; +9 -1: Constants +11 -1: valueOffset +62 -1: (Ljava/util/Hashtable;)V +33 -1: java/lang/CharacterDataPrivateUse +21 -1: Exception in thread " +40 -1: ()Ljava/util/Set; +12 -1: Asia/Yerevan +40 -1: (Ljava/lang/Throwable;)Ljava/lang/Error; +25 -1: (IS)Ljava/nio/ByteBuffer; +7 -1: (I[CI)I +45 -1: java/nio/charset/UnmappableCharacterException +23 -1: java/util/WeakHashMap$1 +21 -1: setFXLaunchParameters +1250 -1: ADANDAEAREAFAFGAGATGAIAIAALALBAMARMANANTAOAGOAQATAARARGASASMATAUTAUAUSAWABWAXALAAZAZEBABIHBBBRBBDBGDBEBELBFBFABGBGRBHBHRBIBDIBJBENBLBLMBMBMUBNBRNBOBOLBQBESBRBRABSBHSBTBTNBVBVTBWBWABYBLRBZBLZCACANCCCCKCDCODCFCAFCGCOGCHCHECICIVCKCOKCLCHLCMCMRCNCHNCOCOLCRCRICUCUBCVCPVCWCUWCXCXRCYCYPCZCZEDEDEUDJDJIDKDNKDMDMADODOMDZDZAECECUEEESTEGEGYEHESHERERIESESPETETHFIFINFJFJIFKFLKFMFSMFOFROFRFRAGAGABGBGBRGDGRDGEGEOGFGUFGGGGYGHGHAGIGIBGLGRLGMGMBGNGINGPGLPGQGNQGRGRCGSSGSGTGTMGUGUMGWGNBGYGUYHKHKGHMHMDHNHNDHRHRVHTHTIHUHUNIDIDNIEIRLILISRIMIMNININDIOIOTIQIRQIRIRNISISLITITAJEJEYJMJAMJOJORJPJPNKEKENKGKGZKHKHMKIKIRKMCOMKNKNAKPPRKKRKORKWKWTKYCYMKZKAZLALAOLBLBNLCLCALILIELKLKALRLBRLSLSOLTLTULULUXLVLVALYLBYMAMARMCMCOMDMDAMEMNEMFMAFMGMDGMHMHLMKMKDMLMLIMMMMRMNMNGMOMACMPMNPMQMTQMRMRTMSMSRMTMLTMUMUSMVMDVMWMWIMXMEXMYMYSMZMOZNANAMNCNCLNENERNFNFKNGNGANINICNLNLDNONORNPNPLNRNRUNUNIUNZNZLOMOMNPAPANPEPERPFPYFPGPNGPHPHLPKPAKPLPOLPMSPMPNPCNPRPRIPSPSEPTPRTPWPLWPYPRYQAQATREREUROROURSSRBRURUSRWRWASASAUSBSLBSCSYCSDSDNSESWESGSGPSHSHNSISVNSJSJMSKSVKSLSLESMSMRSNSENSOSOMSRSURSSSSDSTSTPSVSLVSXSXMSYSYRSZSWZTCTCATDTCDTFATFTGTGOTHTHATJTJKTKTKLTLTLSTMTKMTNTUNTOTONTRTURTTTTOTVTUVTWTWNTZTZAUAUKRUGUGAUMUMIUSUSAUYURYUZUZBVAVATVCVCTVEVENVGVGBVIVIRVNVNMVUVUTWFWLFWSWSMYEYEMYTMYTZAZAFZMZMBZWZWE +60 -1: Ljava/util/Set;>; +24 -1: ()Ljava/security/Policy; +7 -1: initted +44 -1: java/util/Collections$UnmodifiableCollection +12 -1: Pacific/Apia +23 -1: checkProxyPackageAccess +7 -1: (I[CI)V +64 -1: ([Ljava/lang/Object;IILjava/lang/Object;Ljava/util/Comparator;)I +16 -1: getJavaNioAccess +7 -1: reverse +7 -1: nocerts +16 -1: activeGroupCount +34 -1: java/util/jar/JarFile$JarFileEntry +7 -1: loaders +9 -1: toRadians +24 -1: java/util/HashMap$KeySet +37 -1: (Ljava/lang/Class;)Ljava/lang/Object; +6 -1: getRef +6 -1: H_DASH +17 -1: LinkageError.java +66 -1: (Ljava/lang/invoke/MethodTypeForm;)Ljava/lang/invoke/MethodHandle; +41 -1: (Ljava/nio/ByteBuffer;)Ljava/util/BitSet; +10 -1: addMinutes +58 -1: ([TT;II)Ljava/util/Spliterator; +9 -1: parseJars +13 -1: getUnsignedCS +28 -1: (Ljava/util/AbstractList;I)V +22 -1: threadLocalRandomProbe +19 -1: newDirectByteBuffer +27 -1: Filter already registered: +8 -1: unescape +31 -1: sun/misc/URLClassPath$JarLoader +6 -1: TAIWAN +53 -1: ()Ljava/util/ListIterator; +17 -1: REVERSE_THRESHOLD +31 -1: Java(TM) SE Runtime Environment +7 -1: SECONDS +70 -1: (Ljava/util/function/ToLongFunction<-TT;>;)Ljava/util/Comparator; +7 -1: BLOCKED +6 -1: Caches +63 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)V +2 -1: : +210 -1: (Ljava/util/Map;Ljava/lang/annotation/Annotation;>;Ljava/util/Map;Ljava/lang/annotation/Annotation;>;I)V +153 -1: (JLjava/util/function/BiFunction;Ljava/util/Map$Entry;+Ljava/util/Map$Entry;>;)Ljava/util/Map$Entry; +22 -1: ()Ljava/lang/Class<*>; +28 -1: Ljava/lang/OutOfMemoryError; +19 -1: writeFileDescriptor +39 -1: Ljava/util/LinkedHashMap$Entry; +26 -1: (ILjava/util/Collection;)Z +18 -1: getEncodedInternal +16 -1: ForEachValueTask +23 -1: (Ljava/util/List<*>;I)V +19 -1: SharedArchiveLoader +20 -1: probeBackupLocations +24 -1: java/lang/StringCoding$1 +28 -1: lookupContentHandlerClassFor +36 -1: ()Lsun/misc/Launcher$ExtClassLoader; +27 -1: reflectionFactoryAccessPerm +14 -1: ACCESSOR_FORMS +35 -1: ([JII)Ljava/util/stream/LongStream; +34 -1: ISO-8859-1 charset not available: +8 -1: cscesu-8 +2 -1: ;/ +17 -1: typeToPackageName +34 -1: (Ljava/net/URL;)Ljava/lang/String; +5 -1: (IZ)V +25 -1: Prohibited package name: +51 -1: (Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V +108 -1: (JLjava/util/function/ToIntFunction;>;ILjava/util/function/IntBinaryOperator;)I +12 -1: soleInstance +27 -1: (Ljava/io/BufferedReader;)V +71 -1: (Ljava/nio/charset/CodingErrorAction;)Ljava/nio/charset/CharsetDecoder; +17 -1: Ljava/lang/Class; +38 -1: (Ljava/lang/String;)Ljava/lang/Double; +10 -1: viewAsType +22 -1: (Ljava/io/DataInput;)I +22 -1: (Ljava/io/DataInput;)J +105 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/WrongMethodTypeException; +16 -1: setJavaNetAccess +73 -1: (ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/util/HashMap$Node; +22 -1: (Ljava/io/DataInput;)V +14 -1: getHostAddress +37 -1: sun/reflect/annotation/TypeAnnotation +14 -1: ENCLOSING_MARK +5 -1: FALSE +14 -1: preDefineClass +9 -1: newKeySet +18 -1: getWaitQueueLength +32 -1: ()Lsun/misc/URLClassPath$Loader; +54 -1: (Ljava/nio/CharBuffer;I)Ljava/nio/charset/CoderResult; +3 -1: SEP +45 -1: (ITK;TV;Ljava/util/Hashtable$Entry;)V +17 -1: getDeclaredFields +7 -1: getDate +10 -1: getClasses +240 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;Ljava/util/function/ToIntFunction;ILjava/util/function/IntBinaryOperator;)V +12 -1: WeakClassKey +14 -1: LF_GEN_INVOKER +25 -1: Ljava/lang/StringBuilder; +2 -1: > +9 -1: getJarMap +4 -1: asin +37 -1: (Ljava/net/URLStreamHandlerFactory;)V +30 -1: not a constructor type or name +4 -1: main +22 -1: java/io/FilenameFilter +22 -1: sun.java.launcher.diag +30 -1: ()Ljava/util/Spliterator; +57 -1: ;>(Ljava/util/List;)V +86 -1: (Ljava/lang/ThreadLocal;>;)TT; +18 -1: canBeCalledVirtual +9 -1: Shift_JIS +24 -1: ()Ljava/util/ArrayDeque; +32 -1: (Ljava/lang/Class$MethodArray;)V +22 -1: java/lang/StringCoding +33 -1: sun/util/locale/LocaleObjectCache +20 -1: Sorry, deque too big +38 -1: java/lang/Throwable$WrappedPrintWriter +25 -1: (Ljava/io/InputStream;J)J +44 -1: (Ljava/security/Permission;)Ljava/util/List; +5 -1: thunk +5 -1: props +15 -1: getLastModified +120 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/util/HashMap;>;)V +146 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MemberName;Ljava/lang/Class;Ljava/lang/invoke/MethodHandleImpl$1;)V +27 -1: parseExtensionsDependencies +10 -1: getRawType +39 -1: (Ljava/nio/charset/CodingErrorAction;)V +22 -1: ObjectStreamField.java +6 -1: handle +11 -1: hasPrevious +18 -1: instanceof Float: +52 -1: (ZLjava/io/OutputStream;Ljava/nio/charset/Charset;)V +4 -1: make +13 -1: isIdeographic +26 -1: java/util/HashMap$EntrySet +51 -1: (Ljava/util/Hashtable;)[Ljava/util/Hashtable$Entry; +91 -1: (Ljava/lang/CharSequence;Ljava/lang/Iterable<+Ljava/lang/CharSequence;>;)Ljava/lang/String; +13 -1: makeAllocator +10 -1: , headless +20 -1: expungeStaleElements +58 -1: sun/reflect/annotation/TypeAnnotation$TypeAnnotationTarget +41 -1: ([Ljava/lang/Object;Ljava/lang/Class$1;)V +50 -1: (I)Ljava/util/Iterator; +7 -1: TreeBin +21 -1: Ljava/io/IOException; +56 -1: (I[Ljava/lang/Class;)[Ljava/lang/invoke/LambdaForm$Name; +6 -1: LOCFLG +6 -1: DIRECT +3 -1: SIG +37 -1: java/security/NoSuchProviderException +39 -1: " with illegal data type conversion to +16 -1: getCodeSourceURL +51 -1: java/util/concurrent/ConcurrentHashMap$EntrySetView +47 -1: (Ljava/util/ArrayList;Ljava/util/ArrayList$1;)V +6 -1: delete +38 -1: sun/reflect/UnsafeFieldAccessorFactory +11 -1: isDestroyed +140 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)Z +9 -1: unaligned +36 -1: ()Lsun/misc/Launcher$AppClassLoader; +57 -1: (Ljava/lang/String;Ljava/util/Locale;)[Ljava/lang/String; +37 -1: sun/reflect/annotation/AnnotationType +49 -1: ([TT;)Ljava/util/List; +24 -1: (S)Ljava/nio/ByteBuffer; +6 -1: ([DD)I +9 -1: setTarget +29 -1: (IF)Ljava/lang/StringBuilder; +12 -1: forBasicType +10 -1: (IIII[BI)V +8 -1: ([DIID)I +9 -1: BASE_YEAR +19 -1: ()Ljava/lang/Error; +42 -1: (Ljava/util/Map;)V +6 -1: ([DD)V +14 -1: Illegal size: +8 -1: ([DIID)V +7 -1: (II[I)I +17 -1: java_profile_name +28 -1: java/util/AbstractCollection +43 -1: (Ljava/net/URL;)[Ljava/security/CodeSource; +62 -1: (Lsun/misc/URLClassPath$JarLoader;)Ljava/net/URLStreamHandler; +33 -1: [Ljava/util/HashMap$Node; +15 -1: (Native Method) +11 -1: fileNameMap +26 -1: ()Ljava/util/ListIterator; +25 -1: java/util/LinkedList$Node +18 -1: SELECT_ALTERNATIVE +35 -1: (Ljava/lang/Object;)Ljava/util/Set; +19 -1: java/io/IOException +16 -1: : already loaded +9 -1: image/gif +6 -1: (TE;)I +25 -1: (Ljava/util/Properties;)V +40 -1: (Ljava/lang/String;)Ljava/nio/file/Path; +19 -1: checkedNavigableMap +9 -1: checkInt( +17 -1: getContentTypeFor +26 -1: ()Ljava/io/FileDescriptor; +69 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V +6 -1: (TE;)V +25 -1: WARNING: Default charset +14 -1: ZipFile closed +2 -1: CA +6 -1: (TE;)Z +64 -1: java/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask +15 -1: FileSystem.java +75 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V +10 -1: FileLoader +44 -1: (Lsun/util/PreHashedMap;)[Ljava/lang/Object; +19 -1: availableProcessors +2 -1: CN +36 -1: ([JII)Ljava/util/Spliterator$OfLong; +11 -1: access$1100 +18 -1: getFieldAtIfLoaded +30 -1: PrivilegedActionException.java +6 -1: EUC-JP +20 -1: (F)Ljava/lang/Float; +22 -1: unable to instantiate +31 -1: java/lang/reflect/ReflectAccess +23 -1: (Ljava/lang/Object;JC)V +3 -1: get +59 -1: ([TT;IILjava/util/Comparator<-TT;>;)V +2 -1: DE +13 -1: GMT_ID_LENGTH +7 -1: execute +12 -1: MethodHandle +18 -1: AllPermission.java +54 -1: (Ljava/util/Locale;)Lsun/util/locale/LocaleExtensions; +23 -1: MapReduceKeysToLongTask +12 -1: varargsArray +23 -1: java/util/jar/JarFile$1 +23 -1: java/util/jar/JarFile$2 +23 -1: java/util/jar/JarFile$3 +12 -1: getAndUpdate +13 -1: reserveMemory +17 -1: expungeStaleEntry +6 -1: EUC-KR +120 -1: Ljava/lang/ref/WeakReference;Ljava/util/Map$Entry; +69 -1: (Ljava/lang/StringBuffer;Ljava/lang/String;)Ljava/util/regex/Matcher; +26 -1: ()Ljava/util/NavigableMap; +7 -1: L_PCHAR +23 -1: (Ljava/lang/String$1;)V +4 -1: KEYS +37 -1: (Ljava/util/List;Ljava/lang/Object;)I +31 -1: Ljava/lang/ArithmeticException; +15 -1: [Ljava/net/URL; +37 -1: (Ljava/util/List;Ljava/lang/Object;)V +18 -1: MAX_HIGH_SURROGATE +6 -1: (JCZ)V +4 -1: mark +17 -1: setMethodAccessor +21 -1: java/io/ExpiringCache +21 -1: PrivilegedAction.java +21 -1: MappedByteBuffer.java +2 -1: FR +10 -1: copyMemory +8 -1: L_SERVER +13 -1: assertionLock +12 -1: searchValues +46 -1: (Ljava/util/Collection<*>;Ljava/lang/Object;)I +21 -1: ProtectionDomainCache +32 -1: USE_PREDEFINED_INTERPRET_METHODS +2 -1: GB +16 -1: getFinalRefCount +23 -1: Ljava/lang/ClassLoader; +4 -1: mask +94 -1: (Ljava/util/function/ToDoubleFunction<-TT;>;)Ljava/util/Comparator; +4 -1: bind +41 -1: (Ljava/lang/Class<*>;I)Ljava/lang/Object; +9 -1: COUNT_GWT +16 -1: DASH_PUNCTUATION +24 -1: UNICODE_LOCALE_EXTENSION +15 -1: checkInvariants +10 -1: stringSize +12 -1: deepHashCode +30 -1: java/security/cert/Certificate +19 -1: America/Los_Angeles +19 -1: unmappableForLength +6 -1: UTF-16 +10 -1: methodType +21 -1: sun/misc/URLClassPath +19 -1: META-INF/INDEX.LIST +10 -1: jniVersion +6 -1: IBM437 +29 -1: sun/reflect/FieldAccessorImpl +21 -1: ()Ljava/lang/Package; +32 -1: java/security/SecurityPermission +57 -1: (Lsun/util/calendar/Era;)Lsun/util/calendar/CalendarDate; +34 -1: [Ljava/util/concurrent/locks/Lock; +11 -1: replacement +20 -1: ()Ljava/lang/String; +6 -1: resize +12 -1: UTF_32BE_BOM +26 -1: (Ljava/util/jar/JarFile;)V +24 -1: DEFAULT_INITIAL_CAPACITY +87 -1: (ILjava/lang/Object;Ljava/lang/Class;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode; +74 -1: (Ljava/util/jar/JarFile;)Ljava/util/Enumeration; +18 -1: parameterSlotDepth +26 -1: (Ljava/util/jar/JarFile;)Z +18 -1: makePlatformString +24 -1: doPrivilegedWithCombiner +48 -1: (Ljava/lang/String;)Lsun/util/calendar/ZoneInfo; +27 -1: ()Ljava/lang/ref/Reference; +40 -1: java/util/ArrayList$ArrayListSpliterator +67 -1: ([Ljava/lang/Object;IILjava/util/Comparator;[Ljava/lang/Object;II)V +2 -1: ID +19 -1: stringPropertyNames +28 -1: (Ljava/util/Collections$1;)V +12 -1: STATE_YELLOW +12 -1: isNormalized +10 -1: fromIndex( +16 -1: getFloatVolatile +37 -1: Lsun/util/calendar/BaseCalendar$Date; +10 -1: properties +17 -1: peakFinalRefCount +102 -1: (Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode; +68 -1: (Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/DirectMethodHandle; +2 -1: IT +9 -1: ([BI[BI)V +51 -1: scl permissions SecureClassLoader assigns +36 -1: (Ljava/util/Set;Ljava/lang/Object;)V +11 -1: ([SII[SII)V +21 -1: sun.io.useCanonCaches +18 -1: Illegal capacity: +22 -1: (Ljava/lang/Integer;)I +83 -1: ([Ljava/lang/Object;Ljava/lang/StringBuilder;Ljava/util/Set<[Ljava/lang/Object;>;)V +65 -1: (Ljava/util/HashMap;[Ljava/util/HashMap$Node;II)V +17 -1: java/util/Objects +48 -1: (ILjava/util/List;)Ljava/lang/invoke/LambdaForm; +31 -1: java/util/Properties$XmlSupport +10 -1: L_LOWALPHA +13 -1: long overflow +25 -1: NullPointerException.java +32 -1: (I)Ljava/lang/StackTraceElement; +34 -1: ()[Ljava/lang/reflect/Constructor; +2 -1: JP +3 -1: SST +12 -1: ShortCountry +48 -1: (Ljava/util/stream/Collector;)Ljava/lang/Object; +29 -1: Lsun/reflect/CallerSensitive; +10 -1: addElement +12 -1: lastReturned +6 -1: putInt +34 -1: sun.misc.JarIndex.metaInfFilenames +13 -1: getBaseLocale +20 -1: StringTokenizer.java +8 -1: entrySet +11 -1: getTypeName +17 -1: America/Sao_Paulo +5 -1: \t... +35 -1: (Lsun/util/calendar/CalendarDate;)I +28 -1: java/lang/StackOverflowError +35 -1: (Lsun/util/calendar/CalendarDate;)J +10 -1: logicalAnd +18 -1: csISOLatinCyrillic +43 -1: (Ljava/lang/String;II)Ljava/nio/CharBuffer; +73 -1: (Ljava/lang/Class<*>;[Ljava/lang/Class<*>;Z)Ljava/lang/invoke/MethodType; +14 -1: aliases_MS1250 +14 -1: aliases_MS1251 +17 -1: getImplMethodKind +17 -1: getLastAccessTime +14 -1: aliases_MS1252 +14 -1: aliases_MS1253 +35 -1: (Lsun/util/calendar/CalendarDate;)V +2 -1: KR +14 -1: aliases_MS1254 +14 -1: getGenericInfo +8 -1: utf_32be +14 -1: aliases_MS1257 +35 -1: (Lsun/util/calendar/CalendarDate;)Z +13 -1: StringEncoder +7 -1: LDT2037 +7 -1: generic +2 -1: L9 +45 -1: ([DLjava/util/function/IntToDoubleFunction;)V +17 -1: isOtherAlphabetic +9 -1: implWrite +24 -1: PC-Multilingual-850+euro +12 -1: valueMatches +78 -1: (Ljava/lang/String;Lsun/util/locale/ParseStatus;)Lsun/util/locale/LanguageTag; +3 -1: gmt +19 -1: (Ljava/io/Reader;)V +25 -1: (JJ)Ljava/nio/ByteBuffer; +7 -1: val$url +26 -1: (Ljava/nio/ByteBuffer;IJ)V +10 -1: isImplicit +19 -1: getDeclaredClasses0 +4 -1: (I)B +4 -1: (I)C +4 -1: (I)D +9 -1: byteValue +4 -1: (I)F +5 -1: ([J)I +6 -1: isLive +5 -1: sleep +4 -1: (I)I +4 -1: (I)J +6 -1: outBuf +77 -1: Ljava/util/AbstractCollection;Ljava/util/Set; +4 -1: (I)S +5 -1: ([J)V +4 -1: (I)V +30 -1: (I[C)Ljava/lang/StringBuilder; +14 -1: intBitsToFloat +4 -1: (I)Z +15 -1: MethodType.java +14 -1: resolveSibling +9 -1: Enum.java +111 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;[Ljava/util/concurrent/ConcurrentHashMap$Node;)V +14 -1: IS_CONSTRUCTOR +4 -1: bits +34 -1: java/security/PermissionCollection +9 -1: autoFlush +21 -1: java/util/Collections +12 -1: bindReceiver +20 -1: DMH.invokeStaticInit +11 -1: charsetName +14 -1: x-utf-32be-bom +5 -1: cause +7 -1: handle0 +43 -1: ([I[C[Ljava/lang/invoke/LambdaForm$Name;I)Z +30 -1: getDefaultAllowUserInteraction +18 -1: ConcurrentMap.java +35 -1: (Ljava/lang/String;Z)Ljava/net/URL; +33 -1: Ljava/nio/charset/CharsetDecoder; +36 -1: java/lang/invoke/MethodHandleStatics +34 -1: java/util/concurrent/ConcurrentMap +16 -1: collectArguments +22 -1: packageAssertionStatus +79 -1: (JLjava/util/function/ToLongFunction;JLjava/util/function/LongBinaryOperator;)J +39 -1: Cannot reflectively create enum objects +62 -1: attempt to add a Permission to a readonly PermissionCollection +22 -1: FieldAccessorImpl.java +9 -1: ByteCache +4 -1: TRUE +85 -1: Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Comparable; +17 -1: java.library.path +7 -1: encoder +21 -1: default locale = +11 -1: secondOfDay +37 -1: (Lsun/util/calendar/ZoneInfoFile$1;)V +35 -1: sun/reflect/UnsafeFieldAccessorImpl +24 -1: (Ljava/lang/Object;JJJ)V +16 -1: countStackFrames +24 -1: (Ljava/lang/Object;JJJ)Z +17 -1: nonfairTryAcquire +20 -1: ArrayListSpliterator +5 -1: /DMH= +68 -1: (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String; +2 -1: PI +8 -1: cspcp852 +112 -1: (Ljava/util/List;Ljava/util/Collection;)Ljava/util/Locale; +8 -1: cspcp855 +58 -1: (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z +33 -1: sun/misc/PerfCounter$CoreCounters +6 -1: CESU_8 +7 -1: vmslots +4 -1: Init +7 -1: handler +11 -1: getProperty +10 -1: isVolatile +8 -1: ([J[IJ)I +25 -1: ()Ljava/lang/ClassLoader; +8 -1: asChange +81 -1: (Ljava/net/URLClassLoader;Ljava/lang/String;Lsun/misc/Resource;)Ljava/lang/Class; +12 -1: naturalOrder +8 -1: getState +40 -1: (Ljava/lang/Object;I)[Ljava/lang/String; +36 -1: java/security/AccessControlException +10 -1: linkBefore +48 -1: (Ljava/util/HashMap;[Ljava/util/HashMap$Node;Z)V +26 -1: (Ljava/util/WeakHashMap;)V +23 -1: bad method type alias: +7 -1: putChar +18 -1: basicTypeSignature +33 -1: sun/misc/InvalidJarIndexException +13 -1: getPrivateuse +14 -1: isConstantZero +24 -1: java/io/FilePermission$1 +9 -1: Long.java +19 -1: getLocaleExtensions +10 -1: discovered +17 -1: Invalid file path +12 -1: MAX_MH_ARITY +20 -1: observesDaylightTime +31 -1: Ljava/lang/invoke/MethodHandle; +6 -1: , end +24 -1: java/io/FileDescriptor$1 +12 -1: loadLibrary. +11 -1: Method.java +12 -1: loadLibrary0 +23 -1: java/util/stream/Stream +37 -1: sun.lang.ClassLoader.allowArraySyntax +8 -1: appClass +15 -1: FileReader.java +5 -1: (IF)I +29 -1: [Ljava/lang/ClassValue$Entry; +12 -1: (principals +30 -1: jar jar verification +22 -1: ARRAY_CHAR_BASE_OFFSET +18 -1: newDirectoryStream +4 -1: atan +5 -1: (IF)V +24 -1: (Ljava/lang/Character;)I +2 -1: TH +10 -1: startsWith +9 -1: baseCount +13 -1: canonicalize0 +47 -1: (Ljava/lang/ClassLoader;[Ljava/lang/Class<*>;)V +22 -1: Ljava/io/OutputStream; +2 -1: TW +10 -1: H_RESERVED +19 -1: URLClassLoader.java +16 -1: isAccessibleFrom +59 -1: Ljava/util/Hashtable; +33 -1: java/lang/invoke/ConstantCallSite +14 -1: Ljava/net/URL; +12 -1: deleteOnExit +20 -1: MAX_SKIP_BUFFER_SIZE +30 -1: [Ljava/lang/ref/WeakReference; +15 -1: contentPathProp +9 -1: initCause +53 -1: (Ljava/util/Queue;Ljava/lang/Class;)Ljava/util/Queue; +20 -1: java/util/TimeZone$1 +2 -1: UK +86 -1: (BLjava/lang/Class;Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/DirectMethodHandle; +51 -1: (II[Ljava/lang/Class;)Ljava/lang/invoke/MethodType; +18 -1: Lsun/misc/Cleaner; +31 -1: RuntimeInvisibleTypeAnnotations +2 -1: US +7 -1: makeInt +40 -1: sun/reflect/annotation/AnnotationSupport +28 -1: sun/reflect/misc/ReflectUtil +8 -1: utf_32le +40 -1: (Ljava/lang/Object;JLjava/lang/Object;)V +24 -1: java/nio/file/WatchEvent +66 -1: (Ljava/lang/Class;Ljava/lang/Object;)Ljava/lang/invoke/MethodType; +91 -1: (Ljava/lang/String;[BIILjava/security/ProtectionDomain;Ljava/lang/String;)Ljava/lang/Class; +114 -1: (Ljava/lang/ThreadLocal;ILjava/lang/ThreadLocal$ThreadLocalMap$Entry;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry; +20 -1: internalWriteEntries +79 -1: (TT;Ljava/util/function/Supplier;)TT; +14 -1: bitIndex < 0: +88 -1: (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object; +6 -1: , len +28 -1: java/io/BufferedOutputStream +11 -1: System.java +11 -1: csISOLatin1 +11 -1: csISOLatin2 +28 -1: Ljava/io/OutputStreamWriter; +27 -1: IllegalAccessException.java +11 -1: csISOLatin4 +14 -1: isDaylightTime +11 -1: csISOLatin5 +21 -1: getYearLengthInMonths +13 -1: canonicalizes +93 -1: "'s signer information does not match signer information of other classes in the same package +32 -1: ()Lsun/management/GcInfoBuilder; +37 -1: (IILjava/nio/charset/CoderResult$1;)V +10 -1: stateNames +46 -1: (Ljava/lang/String;)Ljava/nio/charset/Charset; +21 -1: acquireMethodAccessor +2 -1: X- +32 -1: java/security/ProtectionDomain$1 +5 -1: atan2 +32 -1: java/security/ProtectionDomain$2 +32 -1: java/security/ProtectionDomain$3 +41 -1: malformed input: partial character at end +18 -1: dropParameterTypes +44 -1: (Ljava/lang/String;)Ljava/lang/StringBuffer; +18 -1: CalendarUtils.java +5 -1: month +84 -1: Ljava/lang/Object;Ljava/security/PrivilegedExceptionAction; +33 -1: sun/misc/JavaNioAccess$BufferPool +18 -1: SearchMappingsTask +38 -1: DelegatingConstructorAccessorImpl.java +80 -1: (Ljava/lang/invoke/MemberName;Ljava/lang/Class<*>;)Ljava/lang/invoke/MemberName; +8 -1: instance +54 -1: Parameter annotations don't match number of parameters +14 -1: createConstant +35 -1: java/lang/invoke/MemberName$Factory +4 -1: scrt +34 -1: Ljava/lang/InstantiationException; +20 -1: allowUserInteraction +15 -1: java/util/Deque +16 -1: forEachRemaining +35 -1: (J)Lsun/util/calendar/CalendarDate; +13 -1: no such field +25 -1: java/nio/file/FileSystems +16 -1: expectedModCount +44 -1: (Ljava/io/File;ILjava/nio/charset/Charset;)V +12 -1: createString +15 -1: useDaylightTime +31 -1: java/util/Properties$LineReader +111 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Class<*>;I[Ljava/lang/invoke/MemberName;)I +16 -1: java/util/Locale +26 -1: URLClassPath.getResource(" +58 -1: (Ljava/util/SortedMap;Ljava/lang/Class;Ljava/lang/Class;)V +10 -1: appendTail +7 -1: cleaner +78 -1: (Lsun/nio/cs/FastCharsetProvider;Ljava/lang/String;)Ljava/nio/charset/Charset; +18 -1: convertOldISOCodes +4 -1: year +38 -1: java/lang/ReflectiveOperationException +28 -1: (Ljava/lang/StringBuffer;B)V +27 -1: (D)Ljava/lang/StringBuffer; +17 -1: emptyNavigableSet +7 -1: indices +10 -1: is sealed +21 -1: SPECIFICATION_VERSION +3 -1: TE; +8 -1: addMonth +24 -1: java/util/HashMap$Values +17 -1: SEARCH_ALL_SUPERS +18 -1: uncaught exception +14 -1: declaredFields +2 -1: [B +2 -1: [C +8 -1: ABSTRACT +2 -1: [D +2 -1: [F +2 -1: [I +2 -1: [J +5 -1: false +36 -1: (Ljava/net/URL;Ljava/lang/String;J)V +12 -1: equalContext +11 -1: VOID_RESULT +2 -1: [S +24 -1: (JLjava/lang/Object;JJ)V +36 -1: Ljava/security/PermissionCollection; +2 -1: [Z +17 -1: floatToRawIntBits +2 -1: [] +21 -1: ()[Ljava/lang/Thread; +20 -1: [Ljava/lang/Integer; +42 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Z)V +19 -1: checkPrintJobAccess +40 -1: (Ljava/lang/Object;)Ljava/lang/Class<*>; +31 -1: (Lsun/reflect/FieldAccessor;Z)V +10 -1: reallyPoll +52 -1: (Ljava/lang/ref/Reference;)Ljava/lang/ref/Reference; +100 -1: (JLjava/util/function/Function<-TV;+TU;>;Ljava/util/function/Consumer<-TU;>;)V +19 -1: CheckedNavigableMap +48 -1: (Ljava/lang/String;)Ljava/lang/RuntimeException; +35 -1: java/util/Hashtable$ValueCollection +89 -1: (JLjava/util/function/ToDoubleFunction<-TK;>;DLjava/util/function/DoubleBinaryOperator;)D +10 -1: Stack.java +57 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;I)V +12 -1: getTimeOfDay +12 -1: reduceValues +22 -1: warnUnsupportedCharset +34 -1: (Ljava/lang/ref/Reference<+TS;>;)Z +31 -1: EEE, dd MMM yyyy HH:mm:ss 'GMT' +19 -1: setCachedLambdaForm +21 -1: (I)Ljava/lang/Object; +85 -1: (Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;Ljava/util/Locale$1;)V +36 -1: java/security/AccessControlContext$1 +27 -1: Lsun/net/www/MessageHeader; +23 -1: ()[Ljava/lang/Class<*>; +14 -1: refKindIsValid +41 -1: sun/reflect/NativeConstructorAccessorImpl +6 -1: binary +23 -1: ()Ljava/nio/CharBuffer; +8 -1: getSpace +45 -1: bootstrap method failed to produce a CallSite +15 -1: getISO3Language +17 -1: TRANSITION_NSHIFT +163 -1: ([Ljava/lang/String;Ljava/util/Map;>;)Ljava/util/Map;>; +7 -1: os.name +38 -1: java/util/function/IntToDoubleFunction +8 -1: checkInt +21 -1: java/lang/VerifyError +42 -1: sunpkcs11 SunPKCS11 provider debugging +19 -1: URI is not absolute +23 -1: java/io/DataInputStream +53 -1: (Ljava/lang/Object;)Ljava/nio/charset/CharsetEncoder; +2 -1: _# +41 -1: (Ljava/io/FilenameFilter;)[Ljava/io/File; +26 -1: Ljava/util/jar/Attributes; +7 -1: collect +17 -1: Lsun/misc/Unsafe; +97 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; +78 -1: (Ljava/util/Enumeration;)Ljava/util/ArrayList; +28 -1: (II)Ljava/lang/StringBuffer; +54 -1: (Ljava/lang/reflect/Constructor<*>;)Ljava/lang/String; +28 -1: ()Ljava/util/ResourceBundle; +48 -1: java/util/ArraysParallelSortHelpers$FJInt$Sorter +9 -1: no access +57 -1: Ljava/lang/ref/ReferenceQueue; +7 -1: getPerf +11 -1: getClassAt0 +11 -1: rtypeOffset +20 -1: thread can't be null +12 -1: addArguments +12 -1: utf_32le_bom +21 -1: allowThreadSuspension +25 -1: defaultExpectedLineLength +11 -1: removeFirst +13 -1: reduceEntries +20 -1: Read-ahead limit < 0 +57 -1: (Ljava/util/Collection<-TT;>;[TT;)Z +39 -1: ()Ljava/lang/invoke/MemberName$Factory; +13 -1: ZipCoder.java +16 -1: java/lang/Thread +27 -1: java/lang/NoSuchMethodError +66 -1: (Ljava/util/jar/JarFile;Ljava/net/URL;)[Ljava/security/CodeSource; +22 -1: java/lang/StringBuffer +3 -1: TK; +34 -1: (I)Ljava/lang/invoke/MethodHandle; +30 -1: (Ljava/lang/reflect/Method;Z)V +13 -1: file.encoding +14 -1: removeTreeNode +27 -1: sun/misc/JavaSecurityAccess +58 -1: ([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object; +19 -1: equalLimitedContext +22 -1: appendVmSynonymMessage +10 -1: applyAsInt +23 -1: privateGetPublicMethods +11 -1: dumpThreads +25 -1: RuntimeVisibleAnnotations +37 -1: (IF)Ljava/lang/AbstractStringBuilder; +18 -1: getBooleanVolatile +27 -1: (Ljava/util/zip/ZipFile;J)V +25 -1: INITIAL_QUOTE_PUNCTUATION +51 -1: (Ljava/util/Map;)[Ljava/lang/annotation/Annotation; +54 -1: (ILjava/lang/Object;)Ljava/lang/AbstractStringBuilder; +20 -1: reflectionDataOffset +2 1: aa +51 -1: (Ljava/util/jar/Attributes$Name;)Ljava/lang/String; +13 -1: transferLinks +18 -1: java/util/Vector$1 +10 -1: ensureOpen +22 -1: getDeclaredConstructor +2 -1: am +19 -1: NF_allocateInstance +66 -1: (Ljava/util/Spliterator$OfDouble;Z)Ljava/util/stream/DoubleStream; +6 -1: ([SS)I +17 -1: newReflectionData +19 -1: subclassAuditsQueue +11 -1: access$1200 +16 -1: ValueSpliterator +18 -1: preparedLambdaForm +38 -1: (Ljava/net/URL;)Ljava/net/InetAddress; +14 -1: getMaxPriority +32 -1: ()[Ljava/lang/StackTraceElement; +67 -1: java/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask +62 -1: (Ljava/util/Hashtable;)V +6 -1: EXTHDR +14 -1: java/util/Date +2 -1: az +6 -1: ([SS)V +15 -1: arrayBaseOffset +9 -1: isTrusted +23 -1: (Ljava/lang/Object;JD)V +2 -1: bb +10 -1: ([BII[BI)V +7 -1: toLower +14 -1: invoke_LLLLL_L +7 -1: jarfile +42 -1: (Ljava/lang/String;)Lsun/misc/PerfCounter; +28 -1: java/lang/ref/Reference$Lock +16 -1: java/util/BitSet +22 -1: jarfile parsing error! +18 -1: jdk_update_version +14 -1: invoke_LLLLL_V +20 -1: java/util/LinkedList +22 -1: erasedInvokerWithDrops +25 -1: timeout value is negative +21 -1: getCalendarProperties +25 -1: not a method descriptor: +2 -1: cb +31 -1: (Lsun/misc/JavaUtilJarAccess;)V +2 -1: cd +43 -1: Lsun/util/PreHashedMap; +12 -1: getEntrySize +2 -1: ce +24 -1: guessContentTypeFromName +2 -1: ch +14 -1: JulianCalendar +22 -1: [Ljava/lang/Cloneable; +122 -1: Ljava/util/AbstractCollection;Ljava/util/Deque;Ljava/lang/Cloneable;Ljava/io/Serializable; +34 -1: Lsun/util/locale/BaseLocale$Cache; +14 -1: LinkedEntrySet +72 -1: Ljava/util/AbstractSet;Ljava/io/Serializable; +39 -1: ()Ljava/io/ObjectOutputStream$PutField; +2 -1: cs +8 -1: indexFor +25 -1: (Ljava/util/List<+TE;>;)V +7 -1: subpath +11 -1: invokeExact +14 -1: setFileNameMap +22 -1: LangReflectAccess.java +8 -1: referent +34 -1: java/util/MissingResourceException +77 -1: (Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package; +11 -1: ([FII[FII)V +17 -1: getParameterCount +18 -1: isMemberAccessible +10 -1: getExtDirs +69 -1: (Ljava/util/List<-TT;>;Ljava/util/List<+TT;>;)V +9 -1: getNextPC +13 -1: setProperties +2 -1: de +16 -1: generateCertPath +6 -1: decode +16 -1: getDefaultParent +50 -1: (Ljava/net/URL;[Ljava/security/cert/Certificate;)V +24 -1: Certificate factory for +35 -1: ()Ljava/lang/reflect/AnnotatedType; +2 -1: ee +12 -1: asLongBuffer +7 -1: PRIVATE +16 -1: aliases_UTF_32BE +2 -1: en +2 -1: eq +7 -1: indexOf +136 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Class<+Ljava/lang/Throwable;>;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle; +24 -1: (Ljava/lang/Class<*>;I)V +72 -1: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/IllegalAccessException; +35 -1: java/util/jar/JavaUtilJarAccessImpl +24 -1: (Ljava/lang/Class<*>;I)Z +2 -1: ex +24 -1: getProtectionDomainCache +101 -1: (Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;JLjava/security/AccessControlContext;)V +3 -1: hit +8 -1: UTF_16BE +2 -1: fd +16 -1: EmptyEnumeration +4 -1: attr +16 -1: fromIndex < -1: +7 -1: getIntB +22 -1: java/io/FilePermission +2 -1: fr +2 -1: fs +7 -1: lazySet +7 -1: getIntL +37 -1: configfile JAAS ConfigFile loading +24 -1: sun/nio/cs/StreamEncoder +40 -1: (Ljava/time/ZoneId;)Ljava/util/TimeZone; +132 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/BiConsumer;)V +2 -1: gc +18 -1: Ljava/lang/Thread; +10 -1: cacheArray +48 -1: (Ljava/util/jar/JarFile;)Ljava/util/jar/JarFile; +61 -1: (Ljava/util/NavigableMap;Ljava/lang/Class;Ljava/lang/Class;)V +8 -1: readByte +7 -1: ([S[S)Z +24 -1: findBootstrapClassOrNull +2 -1: hb +7 -1: REPLACE +45 -1: ()Ljava/util/Enumeration; +10 -1: isOverflow +2 -1: he +13 -1: getCachedJan1 +12 -1: getClassPath +8 -1: leapYear +31 -1: java/lang/invoke/MethodTypeForm +10 -1: ANNOTATION +20 -1: getGregorianCalendar +11 -1: ISO_8859_13 +11 -1: ISO_8859_15 +6 -1: invoke +2 -1: ht +7 -1: ListItr +15 -1: synchronizedMap +7 -1: cleanup +94 -1: (Ljava/lang/Class<+Ljava/lang/annotation/Annotation;>;)Lsun/reflect/annotation/AnnotationType; +3 -1: TT; +69 -1: (JLsun/util/calendar/CalendarDate;)Lsun/util/calendar/Gregorian$Date; +81 -1: (Ljava/util/HashMap$TreeNode;)Z +20 -1: Min. Heap Size: +33 -1: (IZ)Ljava/lang/invoke/MethodType; +2 -1: id +7 -1: ([DI)[D +37 -1: (Ljava/lang/reflect/Constructor<*>;)I +42 -1: ;>([TT;II)V +13 -1: addSuppressed +28 -1: internalMemberNameEnsureInit +2 -1: in +17 -1: getCompressedSize +34 -1: sun/misc/Launcher$AppClassLoader$1 +88 -1: (Ljava/security/DomainCombiner;Ljava/lang/Class<*>;)Ljava/security/AccessControlContext; +37 -1: (Ljava/lang/reflect/Constructor<*>;)V +2 -1: is +2 -1: it +6 -1: ENDOFF +4 -1: void +2 -1: iw +14 -1: emptySortedSet +2 -1: ix +17 -1: unicode-1-1-utf-8 +64 -1: (Ljava/lang/Class;Ljava/util/List;)Ljava/lang/invoke/MethodType; +46 -1: (Lsun/misc/URLClassPath$Loader;)Ljava/net/URL; +2 -1: ja +13 -1: synchronized +76 -1: ([DLjava/util/function/IntToDoubleFunction;)Ljava/util/function/IntConsumer; +11 -1: wrapperType +51 -1: ()Ljava/util/Comparator; +106 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object; +17 -1: removeAllElements +2 -1: ji +24 -1: java/util/Vector$ListItr +14 -1: getNestedTypes +6 -1: L_MARK +27 -1: Source does not fit in dest +2 -1: l1 +2 -1: jp +2 -1: l2 +4 -1: (J)B +57 -1: (Ljava/lang/String;Ljava/util/Locale;I)Ljava/lang/String; +4 -1: (J)C +27 -1: ForEachTransformedValueTask +2 -1: l4 +26 -1: java/util/Hashtable$KeySet +4 -1: (J)D +2 -1: l5 +39 -1: java/security/BasicPermissionCollection +4 -1: (J)F +2 -1: jv +29 -1: MapReduceMappingsToDoubleTask +18 -1: copyFromShortArray +2 -1: l9 +3 -1: TV; +4 -1: (J)I +4 -1: (J)J +23 -1: Lsun/util/calendar/Era; +8 -1: x-EUC-TW +15 -1: checkSetFactory +7 -1: Special +4 -1: (J)S +4 -1: (J)V +7 -1: invoke_ +25 -1: (IC)Ljava/nio/ByteBuffer; +68 -1: (JLjava/util/concurrent/TimeUnit;)Ljava/nio/file/attribute/FileTime; +36 -1: ()Ljava/net/URLStreamHandlerFactory; +4 -1: (J)Z +181 -1: (Ljava/lang/Class<*>;Ljava/lang/ref/SoftReference;>;Ljava/lang/ref/SoftReference;>;)Z +9 -1: getOffset +46 -1: (ILjava/lang/String;)Ljava/lang/StringBuilder; +7 -1: element +15 -1: createByteArray +17 -1: uncaughtException +2 -1: ko +29 -1: java/nio/file/DirectoryStream +15 -1: getISOCountries +246 -1: (BLjava/lang/invoke/MemberName;Ljava/lang/Class<*>;Ljava/lang/Class;)Ljava/lang/invoke/MemberName;^Ljava/lang/IllegalAccessException;^TNoSuchMemberException; +7 -1: invoker +17 -1: langReflectAccess +10 -1: bindSingle +23 -1: java/lang/reflect/Proxy +2 -1: lb +2 -1: lc +29 -1: CREATE_CLASSLOADER_PERMISSION +5 -1: isSet +18 -1: ([Ljava/io/File;)V +15 -1: urlNoFragString +21 -1: DirectByteBuffer.java +15 -1: java.class.path +15 -1: createDirectory +4 -1: GMT +37 -1: sun/reflect/annotation/ExceptionProxy +28 -1: (Ljava/util/Map<+TK;+TV;>;)V +17 -1: getContentHandler +26 -1: GenericDeclRepository.java +56 -1: (Ljava/lang/String;)Ljava/lang/IllegalArgumentException; +15 -1: getJavaIOAccess +39 -1: java/util/Collections$EmptyListIterator +34 -1: java/lang/ConditionalSpecialCasing +82 -1: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/management/GarbageCollectorMBean; +58 -1: (Ljava/util/function/ToIntFunction;)Ljava/util/Comparator; +21 -1: ()Lsun/misc/Launcher; +2 -1: lt +92 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V +8 -1: disjoint +62 -1: (Ljava/net/URL;Ljava/lang/String;Ljava/net/URLStreamHandler;)V +24 -1: ([Ljava/lang/Object;)TT; +4 -1: lmap +8 -1: SATURDAY +12 -1: toStringUTF8 +91 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/BinaryOperator;)Ljava/lang/Object; +46 -1: pkcs11 PKCS11 session manager debugging +27 -1: (Z)Ljava/lang/StringBuffer; +7 -1: forEach +17 -1: (Ljava/io/File;)I +17 -1: (Ljava/io/File;)J +5 -1: RESET +6 -1: isFile +14 -1: Exception.java +8 -1: isPublic +27 -1: computeInitialPreparedForms +50 -1: (BZLjava/lang/Class;)Ljava/lang/invoke/LambdaForm; +19 -1: getAvailableLocales +17 -1: (Ljava/io/File;)V +28 -1: ()Ljava/nio/charset/Charset; +10 -1: appendNull +17 -1: (Ljava/io/File;)Z +23 -1: java/lang/InternalError +2 -1: ne +6 -1: radix +8 -1: checksum +66 -1: (Lsun/net/www/MessageHeader;Ljava/lang/String;Ljava/lang/Object;)V +45 -1: (Ljava/io/FilenameFilter;)[Ljava/lang/String; +8 -1: checkJar +28 -1: default format locale = +13 -1: normalizeTime +26 -1: java/util/AbstractList$Itr +30 -1: java/util/function/IntFunction +7 -1: TIS-620 +12 -1: reverseBytes +2 -1: of +26 -1: java/lang/ClassFormatError +109 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; +10 -1: delimiters +20 -1: indexOfSupplementary +16 -1: aliases_UTF_32LE +134 -1: (Ljava/util/Map;Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/Map; +17 -1: [Ljava/lang/Long; +2 -1: or +12 -1: getClassName +31 -1: (Ljava/nio/charset/Charset;FF)V +6 -1: ([FF)I +39 -1: (Ljava/util/Locale;)[Ljava/lang/String; +33 -1: java/util/WeakHashMap$KeyIterator +8 -1: UTF_16LE +12 -1: isISOControl +75 -1: (Ljava/nio/CharBuffer;Ljava/nio/ByteBuffer;Z)Ljava/nio/charset/CoderResult; +7 -1: ([I[I)Z +28 -1: Self-causation not permitted +6 -1: ([FF)V +14 -1: defaultCharset +12 -1: isJavaLetter +2 -1: pm +39 -1: cannot reflectively invoke MethodHandle +20 -1: getSystemClassLoader +42 -1: ([Ljava/lang/Object;IILjava/lang/Object;)I +56 -1: (Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object; +42 -1: ([Ljava/lang/Object;IILjava/lang/Object;)V +12 -1: ZipFile.java +43 -1: (Ljava/util/zip/ZipFile;)Ljava/lang/String; +22 -1: Ljava/net/InetAddress; +15 -1: getCharVolatile +32 -1: ()[Ljava/lang/reflect/Parameter; +13 -1: delimsChanged +13 -1: getFileSystem +13 -1: METHOD_RETURN +20 -1: sun/misc/PerfCounter +61 -1: (Ljava/util/HashMap;)Ljava/util/HashMap$Node; +8 -1: newIndex +18 -1: getDisplayLanguage +36 -1: (C)Ljava/lang/AbstractStringBuilder; +36 -1: java/lang/StringCoding$StringEncoder +12 -1: forEachEntry +23 -1: [Ljava/io/Serializable; +13 -1: totalCapacity +26 -1: java/io/FileOutputStream$1 +14 -1: signatureArity +90 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/security/cert/Certificate;)V +17 -1: reflectionFactory +6 -1: ibm737 +17 -1: fillInStackTrace0 +16 -1: allocateInstance +52 -1: (Lsun/util/locale/BaseLocale$Key;)Ljava/lang/String; +9 -1: addExtURL +16 -1: copyFromIntArray +65 -1: (Ljava/security/Permission;Z)Ljava/security/PermissionCollection; +57 -1: java/util/concurrent/ConcurrentHashMap$SearchMappingsTask +10 -1: toEpochDay +4 -1: gate +24 -1: sun/nio/cs/UTF_8$Decoder +8 -1: entries2 +18 -1: isCharsetSupported +10 -1: toCustomID +2 -1: rw +33 -1: java/nio/ByteBufferAsFloatBufferB +25 -1: (ID)Ljava/nio/ByteBuffer; +12 -1: addTimeOfDay +61 -1: (Ljava/security/ProtectionDomain;Ljava/security/Permission;)Z +2 -1: sd +25 -1: (Ljava/net/InetAddress;)V +33 -1: java/nio/ByteBufferAsFloatBufferL +2 -1: se +15 -1: hasQueuedThread +24 -1: assertMemberIsConsistent +37 -1: java/util/Collections$UnmodifiableMap +2 -1: sp +20 -1: setJavaUtilJarAccess +96 -1: (Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class; +8 -1: language +76 -1: (Ljava/util/SortedSet;)Ljava/util/SortedSet; +11 -1: findLibrary +61 -1: (Ljava/lang/Class<*>;)Lsun/reflect/annotation/AnnotationType; +6 -1: ([BZ)V +24 -1: DEFAULT_BYTE_BUFFER_SIZE +25 -1: (Ljava/util/ArrayList;I)V +2 -1: th +47 -1: (Ljava/util/Collection;)Ljava/util/Enumeration; +49 -1: (Lsun/misc/URLClassPath$JarLoader;)Ljava/net/URL; +7 -1: ([D[D)Z +2 -1: to +22 -1: java/util/Locale$Cache +8 -1: iterator +30 -1: (Ljava/lang/StringBuilder;IZ)V +17 -1: ()Ljava/util/Set; +2 -1: tr +27 -1: (Ljava/nio/ByteBuffer;ISZ)V +6 -1: method +13 -1: allPermission +9 -1: ruleArray +8 -1: UTC_TIME +10 -1: LF_COUNTER +26 -1: Lsun/nio/cs/StreamDecoder; +25 -1: ()Lsun/util/calendar/Era; +6 -1: LOCHDR +21 -1: sun/net/www/MimeTable +12 -1: Cannot cast +2 -1: us +2 -1: ut +52 -1: Ljava/lang/invoke/MethodHandle$PolymorphicSignature; +6 -1: encode +15 -1: CharBuffer.java +24 -1: (C)Ljava/nio/ByteBuffer; +56 -1: (Ljava/lang/Class<+Ljava/lang/annotation/Annotation;>;)V +18 -1: getEnclosingMethod +56 -1: (Ljava/lang/Class<+Ljava/lang/annotation/Annotation;>;)Z +6 -1: ibm775 +9 -1: (IIIIII)I +44 -1: ([JLjava/util/function/IntToLongFunction;I)V +9 -1: (IIIIII)J +64 -1: (Ljava/util/Locale$LocaleKey;)Lsun/util/locale/LocaleExtensions; +2 -1: x- +2 -1: vm +5 -1: clock +9 -1: (IIIIII)V +10 -1: XmlSupport +19 -1: sun/nio/cs/US_ASCII +10 -1: toRealPath +5 -1: cp367 +6 -1: ST_END +58 -1: [Lsun/util/calendar/ZoneInfoFile$ZoneOffsetTransitionRule; +12 -1: hasSameRules +108 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lsun/util/locale/LocaleExtensions; +22 -1: java/lang/Class$Atomic +4 -1: sync +6 -1: listen +12 -1: firstElement +142 -1: (Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;IILjava/lang/String;[B[B[B)Ljava/lang/reflect/Method; +18 -1: internalProperties +28 -1: (Ljava/lang/StringBuffer;C)V +7 -1: factory +18 -1: ()Ljava/util/List; +50 -1: (Ljava/util/concurrent/CountedCompleter;[D[DIIII)V +44 -1: (Ljava/lang/Class;)Lsun/invoke/util/Wrapper; +83 -1: (JLjava/util/function/ToDoubleFunction;DLjava/util/function/DoubleBinaryOperator;)D +12 -1: erasedType: +53 -1: (Ljava/util/AbstractList;Ljava/util/AbstractList$1;)V +20 -1: Cannot find package +27 -1: java/util/ArrayList$ListItr +10 -1: copyMethod +23 -1: java/lang/ThreadLocal$1 +16 -1: iso_646.irv:1983 +42 -1: (Ljava/lang/Thread;Ljava/lang/Throwable;)V +19 -1: DEFAULT_LOAD_FACTOR +40 -1: ([Ljava/lang/Object;)[Ljava/lang/Object; +10 -1: (JJJ[BII)I +12 -1: singletonMap +8 -1: RESERVED +9 -1: zipAccess +21 -1: SynchronizedSortedMap +4 -1: flag +15 -1: UnmodifiableSet +18 -1: WrappedPrintWriter +7 -1: resume0 +2 -1: yi +10 -1: erasedType +31 -1: CHECK_AWT_EVENTQUEUE_PERMISSION +8 -1: +59 -1: (Ljava/lang/String;)Ljava/security/cert/CertificateFactory; +40 -1: java/lang/management/MemoryManagerMXBean +33 -1: newGetIntIllegalArgumentException +16 -1: iso_646.irv:1991 +58 -1: (Ljava/lang/ClassValue$Entry;)Ljava/lang/ClassValue$Entry; +2 -1: zc +26 -1: (Ljava/util/AbstractMap;)V +6 -1: THROWS +11 -1: toCharArray +64 -1: (Ljava/lang/reflect/Constructor;)Ljava/lang/reflect/Constructor; +2 -1: zh +68 -1: Ljava/lang/ref/SoftReference;>; +25 -1: (Ljava/util/Collection;)V +20 -1: getJdkSpecialVersion +17 -1: getTypeParameters +32 -1: [Ljava/lang/ClassValue$Entry<*>; +25 -1: (Ljava/util/Collection;)Z +26 -1: Lsun/nio/ch/Interruptible; +5 -1: 0.0p0 +5 -1: CACHE +7 -1: namesOK +21 -1: Ljava/lang/Exception; +51 -1: (Ljava/net/URL;Lsun/net/www/protocol/jar/Handler;)V +19 -1: jdk_special_version +66 -1: (Ljava/util/List;)Ljava/util/List; +75 -1: (Ljava/util/Comparator;Ljava/util/function/Function;)Ljava/util/Comparator; +11 -1: Arrays.java +19 -1: (Ljava/lang/Byte;)I +17 -1: java/lang/Class$1 +17 -1: java/lang/Class$2 +17 -1: java/lang/Class$3 +47 -1: java/lang/invoke/MethodHandleImpl$WrappedMember +17 -1: java/lang/Class$4 +44 -1: (Ljava/lang/Throwable;)Ljava/lang/Throwable; +9 -1: charCount +24 -1: ()Ljava/net/FileNameMap; +44 -1: sun/util/locale/provider/TimeZoneNameUtility +17 -1: not an array type +2 -1: {} +24 -1: (Lsun/misc/Launcher$1;)V +12 -1: directMemory +10 -1: parameters +5 -1: java. +14 -1: allocateDirect +51 -1: (Ljava/lang/StringBuffer;)Ljava/lang/StringBuilder; +23 -1: java/nio/file/Watchable +37 -1: createDiagnosticFrameworkNotification +54 -1: (Ljava/lang/Class<*>;Z)Ljava/lang/invoke/MethodHandle; +35 -1: sun/nio/cs/StandardCharsets$Aliases +9 -1: retDelims +11 -1: MAX_ENTRIES +12 -1: CumulateTask +64 -1: java/util/concurrent/ConcurrentHashMap$ForEachTransformedKeyTask +3 -1: iae +12 -1: AF_PUTSTATIC +21 -1: java/lang/Throwable$1 +45 -1: (Ljava/util/HashMap;)Ljava/util/HashMap$Node; +77 -1: (JLjava/util/function/ToIntFunction;ILjava/util/function/IntBinaryOperator;)I +5 -1: after +29 -1: (Ljava/security/CodeSource;)Z +248 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;Ljava/util/function/ToDoubleFunction;DLjava/util/function/DoubleBinaryOperator;)V +6 -1: H_URIC +7 -1: L_DIGIT +7 -1: toNanos +24 -1: (D)Ljava/nio/ByteBuffer; +25 -1: getDiagnosticCommandMBean +6 2: [LFoo; +14 -1: path.separator +16 -1: toUnsignedString +40 -1: DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR +87 -1: (Ljava/security/Permission;[Ljava/security/cert/Certificate;)Ljava/security/Permission; +16 -1: inheritedChannel +11 -1: audio/basic +27 -1: sun.classloader.findClasses +10 -1: queryCount +20 -1: NF_ensureInitialized +12 -1: getBufIfOpen +23 -1: sun/nio/cs/UTF_16LE_BOM +134 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; +17 -1: getImplMethodName +14 -1: linkMethod => +25 -1: Ljava/lang/invoke/Stable; +32 -1: Ljava/lang/annotation/Retention; +7 -1: doInput +9 -1: -_.!~*'() +62 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Class<*>;B)V +18 -1: separateWithCommas +43 -1: com/sun/crypto/provider/CipherBlockChaining +14 -1: createTempFile +9 -1: implFlush +20 -1: getOffsetsByStandard +21 -1: OutOfMemoryError.java +7 -1: jce.jar +46 -1: java/util/Collections$UnmodifiableNavigableMap +30 -1: (Ljava/io/File;)Ljava/io/File; +15 -1: LinkedList.java +15 -1: iso_8859-9:1989 +50 -1: sun/reflect/generics/factory/CoreReflectionFactory +10 -1: : JVM has +19 -1: HeapByteBuffer.java +6 -1: getURL +37 -1: java/security/cert/CertificateFactory +23 -1: getAllowUserInteraction +12 -1: otherParents +25 -1: ARRAY_BOOLEAN_BASE_OFFSET +9 -1: L_UPALPHA +41 -1: ([Ljava/util/Hashtable$Entry<**>;TK;TV;)V +6 -1: LOCHOW +11 -1: access$1300 +30 -1: sun/reflect/MethodAccessorImpl +130 -1: (Ljava/util/List;Ljava/util/Collection;)Ljava/util/List; +9 -1: MALFORMED +38 -1: (Ljava/lang/String;I)Ljava/lang/Short; +26 -1: File format not recognised +12 -1: setTimeOfDay +19 -1: java/lang/Exception +15 -1: getOutputStream +74 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +41 -1: (Ljava/lang/String;Z)Ljava/util/TimeZone; +49 -1: Lsun/reflect/generics/repository/ClassRepository; +8 -1: getCerts +90 -1: (Ljava/lang/Class<*>;ZLjava/lang/Class<*>;)Ljava/util/List; +5 -1: clone +32 -1: ()Ljava/lang/ref/Reference$Lock; +15 -1: caseIgnoreMatch +23 -1: (Ljava/util/Set;)V +25 -1: enumerateStringProperties +9 -1: inherited +4 -1: flip +8 -1: setMonth +38 -1: (Ljava/util/function/Consumer<-TV;>;)V +55 -1: java/util/concurrent/ConcurrentHashMap$ReduceValuesTask +37 -1: getJavaSecurityProtectionDomainAccess +67 -1: (Ljava/util/NavigableSet;Ljava/lang/Class;)Ljava/util/NavigableSet; +10 -1: reduceKeys +14 -1: MAX_CODE_POINT +24 -1: getGenericExceptionTypes +8 -1: fraction +30 -1: java/lang/InterruptedException +46 -1: (Ljava/lang/String;II[BI)Ljava/nio/ByteBuffer; +114 -1: ([Ljava/util/HashMap$Node;Ljava/util/HashMap$TreeNode;)V +66 -1: (Ljava/lang/String;Ljava/lang/Throwable;)Ljava/lang/InternalError; +45 -1: (Ljava/lang/Object;)Ljava/lang/StringBuilder; +8 -1: putLongB +101 -1: (Ljava/nio/channels/ReadableByteChannel;Ljava/nio/charset/CharsetDecoder;I)Lsun/nio/cs/StreamDecoder; +16 -1: standardProvider +14 -1: parameterCount +59 -1: (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/util/List; +8 -1: putLongL +12 -1: (TT;TV;TV;)Z +37 -1: Lsun/reflect/ConstructorAccessorImpl; +11 -1: ([CII[CII)V +14 -1: parameterArray +15 -1: | interpretName +62 -1: (JLjava/util/function/Function;Ljava/util/function/Consumer;)V +30 -1: (Z)Lsun/reflect/FieldAccessor; +19 -1: jvm_special_version +22 -1: java/util/ArrayDeque$1 +12 -1: initVersions +22 -1: java/lang/CharSequence +21 -1: NF_internalMemberName +5 -1: ()TE; +97 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;IZ)Ljava/lang/invoke/MethodHandle; +25 -1: java/nio/MappedByteBuffer +6 -1: addURL +17 -1: isConvertibleFrom +14 -1: extendWithType +9 -1: interrupt +11 -1: floorDivide +16 -1: x-ISO-2022-CN-GB +12 -1: CheckedQueue +7 -1: setLong +64 -1: (Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;)V +108 -1: (Ljava/util/NavigableMap;)Ljava/util/NavigableMap; +38 -1: java/nio/channels/spi/SelectorProvider +17 -1: makeGuardWithTest +20 -1: (Ljava/util/List;Z)V +8 -1: val$path +12 -1: Runtime.java +7 -1: channel +71 -1: ([TT;IILjava/util/function/BinaryOperator;)V +18 -1: initializedHeaders +32 -1: ()[Lsun/launcher/LauncherHelper; +13 -1: jvInitialized +10 -1: getSeconds +7 -1: Decoder +20 -1: getYearFromFixedDate +6 -1: PREFIX +21 -1: sun.boot.library.path +11 -1: FIXED_DATES +33 -1: (JLjava/util/function/Consumer;)V +27 -1: initializeJavaAssertionMaps +13 -1: toOctalString +9 -1: fixResult +10 -1: typeParams +94 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;I)Ljava/util/concurrent/ConcurrentHashMap$Node; +4 -1: Help +11 -1: setIfNotSet +39 -1: java/lang/UnsupportedOperationException +15 -1: zip file closed +8 -1: floorDiv +10 -1: canExecute +10 -1: encodeLoop +18 -1: addRequestProperty +56 -1: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)V +10 -1: superclass +5 -1: close +56 -1: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)Z +6 -1: ignore +32 -1: ()Ljava/lang/ref/ReferenceQueue; +19 -1: java/util/Formatter +27 -1: java/lang/ClassLoaderHelper +23 -1: (Ljava/lang/Object;JZ)V +29 -1: java/nio/file/WatchEvent$Kind +6 -1: CENLEN +4 -1: SIZE +68 -1: (Ljava/util/Deque;)Ljava/util/Queue; +9 -1: isEscaped +12 -1: LF_INTERPRET +22 -1: (I)Ljava/lang/Integer; +60 -1: (Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MemberName; +49 -1: ([Ljava/lang/Class<*>;Ljava/lang/StringBuilder;)V +11 -1: getZipEntry +16 -1: metaInfFilenames +27 -1: (Ljava/lang/StringBuffer;)V +57 -1: (Ljava/lang/Object;)Ljava/util/WeakHashMap$Entry; +76 -1: (Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class<*>; +8 -1: ([CII)[B +27 -1: (Ljava/lang/StringBuffer;)Z +24 -1: getManifestFromReference +8 -1: ([CII)[C +10 -1: H_LOWALPHA +18 -1: FileURLMapper.java +12 -1: fxLaunchMode +24 -1: isMethodHandleInvokeName +17 -1: winTimeToFileTime +19 -1: checkTopLevelWindow +26 -1: MapReduceMappingsToIntTask +13 -1: NORM_PRIORITY +18 -1: lookupViaProviders +30 -1: (I)Ljava/util/LinkedList$Node; +3 -1: UTC +10 -1: UNMAPPABLE +68 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;B)V +9 -1: META-INF/ +13 -1: Iterable.java +71 -1: ([Ljava/lang/reflect/Field;Ljava/lang/String;)Ljava/lang/reflect/Field; +9 -1: setOffset +8 -1: FJObject +50 -1: (Ljava/lang/CharSequence;)Ljava/util/StringJoiner; +23 -1: java/nio/HeapByteBuffer +23 -1: sun/util/PreHashedMap$1 +23 -1: sun/util/PreHashedMap$2 +34 -1: newGetCharIllegalArgumentException +40 -1: jca JCA engine class debugging +39 -1: (Ljava/lang/Object;I)Ljava/lang/Object; +42 -1: (Ljava/lang/String;)Ljava/net/InetAddress; +25 -1: (Ljava/net/FileNameMap;)V +44 -1: (Ljava/util/SortedMap;)Ljava/util/SortedMap; +52 -1: (Ljava/lang/String;Ljava/lang/Long;)Ljava/lang/Long; +27 -1: ()[Ljava/util/HashMap$Node; +29 -1: java/util/EmptyStackException +16 -1: not a field type +14 -1: Ljava/io/File; +28 -1: ()[Ljava/security/Principal; +69 -1: (Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)V +5 -1: ()TK; +10 -1: ISO8859-13 +40 -1: java/lang/invoke/DirectMethodHandle$Lazy +30 -1: The object is not initialized. +10 -1: ISO8859-15 +88 -1: (Ljava/util/List;Ljava/lang/Class;)Ljava/util/List; +25 -1: (ZILjava/lang/String;II)Z +9 -1: stackSize +61 -1: (Ljava/util/Comparator;Ljava/lang/Object;Ljava/lang/Object;)I +16 -1: synchronizedList +90 -1: (Ljava/util/Comparator;Ljava/util/function/Function;Ljava/lang/Object;Ljava/lang/Object;)I +9 -1: nullCheck +174 -1: Ljava/util/concurrent/ConcurrentMap;Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;>; +14 -1: java/lang/Enum +3 -1: int +13 -1: detailMessage +56 -1: java/util/concurrent/ConcurrentHashMap$SearchEntriesTask +10 -1: ISO-8859-1 +10 -1: ISO-8859-2 +10 -1: ISO-8859-3 +10 -1: ISO-8859-4 +10 -1: ISO-8859-5 +10 -1: ISO-8859-6 +24 -1: ([Ljava/lang/Object;II)V +10 -1: ISO-8859-7 +10 -1: ISO-8859-8 +139 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)[Ljava/util/concurrent/ConcurrentHashMap$Node; +10 -1: ISO-8859-9 +5 -1: round +25 -1: DIRECTIONALITY_WHITESPACE +13 -1: NamedFunction +10 -1: startAgent +3 -1: ioe +7 -1: closing +24 -1: appendSchemeSpecificPart +56 -1: sun/reflect/ReflectionFactory$GetReflectionFactoryAction +83 -1: Ljava/lang/Object;Ljava/security/PrivilegedAction; +17 -1: isCharsetDetected +11 -1: getJarFiles +22 -1: getEnclosingMethodInfo +11 -1: setReadable +61 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;)V +10 -1: attachment +34 -1: (Ljava/io/File;)Ljava/lang/String; +18 -1: ZipFileInputStream +15 -1: CodeSource.java +61 -1: (Ljava/util/jar/JarFile;)Ljava/util/List; +7 -1: cp00858 +108 -1: ([Ljava/lang/invoke/LambdaForm$Name;[Ljava/lang/invoke/LambdaForm$Name;II)Ljava/lang/invoke/LambdaForm$Name; +38 -1: ([DII)Ljava/util/Spliterator$OfDouble; +8 -1: val$name +11 -1: LF_REINVOKE +12 -1: validateTime +17 -1: copyFromCharArray +32 -1: throwSetIllegalArgumentException +14 -1: fieldModifiers +52 -1: (Ljava/lang/ClassValue;)Ljava/lang/ClassValue$Entry; +58 -1: (Ljava/io/OutputStream;Ljava/nio/charset/CharsetEncoder;)V +14 -1: generalInvoker +11 -1: interrupted +246 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;Ljava/util/function/ToLongBiFunction;JLjava/util/function/LongBinaryOperator;)V +20 -1: java/util/Dictionary +17 -1: getDoubleVolatile +41 -1: (Ljava/lang/Class<*>;Ljava/lang/Object;)Z +8 -1: intValue +24 -1: (F)Ljava/nio/ByteBuffer; +5 -1: reset +54 -1: (ILjava/util/List;)[Ljava/lang/invoke/LambdaForm$Name; +19 -1: [Ljava/util/Locale; +43 -1: (Ljava/lang/String;II)Ljava/nio/ByteBuffer; +38 -1: ()Ljava/io/ObjectInputStream$GetField; +18 -1: [Locked by thread +10 -1: checkedMap +16 -1: checkedSortedMap +14 -1: illegal symbol +16 -1: TITLECASE_LETTER +4 -1: root +22 -1: (ZLjava/lang/String;)V +27 -1: ([JII)Ljava/nio/LongBuffer; +15 -1: printStackTrace +30 -1: newConstructorForSerialization +14 -1: getPermissions +13 -1: toStringCache +15 -1: equalParamTypes +37 -1: throwFinalFieldIllegalAccessException +35 -1: (Ljava/lang/String;Ljava/io/File;)V +34 -1: java/nio/charset/CoderResult$Cache +3 -1: .\n\n +33 -1: Ljava/nio/charset/CharsetEncoder; +11 -1: lambdaForms +65 -1: (Ljava/lang/Class;)TT; +39 -1: (CLjava/lang/Class;Ljava/lang/Object;)Z +3 -1: ise +14 -1: forLanguageTag +45 -1: ([Ljava/lang/Class<*>;[Ljava/lang/Class<*>;)Z +36 -1: RuntimeInvisibleParameterAnnotations +12 -1: binarySearch +24 -1: getAssociatedAnnotations +10 -1: decoderFor +6 -1: ibm813 +10 -1: logicalXor +10 -1: setVarargs +71 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Void;)V +4 -1: cast +6 -1: ibm819 +23 -1: getParentDelegationTime +8 -1: ([FII)[F +4 -1: .tmp +6 -1: (JII)J +27 -1: ()Ljava/lang/ref/Finalizer; +9 -1: sunec.jar +22 -1: java/net/URLConnection +41 -1: (Ljava/lang/Runnable;Ljava/lang/String;)V +20 -1: SecurityManager.java +18 -1: getZipFileOpenTime +7 -1: country +13 -1: inflaterCache +4 -1: +17 -1: java/lang/Runtime +125 -1: (Lsun/management/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V +24 -1: java/util/ResourceBundle +64 -1: Ljava/util/Hashtable; +79 -1: ([Ljava/util/WeakHashMap$Entry;[Ljava/util/WeakHashMap$Entry;)V +8 -1: x-ibm737 +39 -1: (Ljava/security/AccessControlContext;)Z +21 -1: (Ljava/lang/Class;I)V +4 -1: - +15 -1: calculateFields +22 -1: Ljava/util/Properties; +8 -1: getArray +21 -1: (Ljava/lang/Class;I)Z +41 -1: (Ljava/lang/ThreadGroup;)Ljava/lang/Void; +17 -1: Ljava/io/Console; +115 -1: (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;[Ljava/security/Permission;)Ljava/lang/Object; +12 -1: nextThreadID +81 -1: (Ljava/net/URLClassLoader;Ljava/lang/SecurityManager;Ljava/security/Permission;)V +23 -1: ARRAY_SHORT_BASE_OFFSET +10 -1: interpret_ +144 -1: (Ljava/net/URL;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V +20 -1: isIPv6LiteralAddress +13 -1: launcher_name +36 -1: java/util/function/IntToLongFunction +38 -1: java/util/WeakHashMap$EntrySpliterator +8 -1: copyInto +3 -1: ACT +11 -1: metafactory +31 -1: ([BLjava/nio/charset/Charset;)V +30 -1: java/lang/annotation/Retention +13 -1: getYearLength +42 -1: java/util/AbstractMap$SimpleImmutableEntry +31 -1: ()Ljava/lang/invoke/MemberName; +21 -1: sun/misc/JavaIOAccess +16 -1: jdk_build_number +8 -1: ST_RESET +96 -1: (BLjava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MemberName; +13 -1: getTypeString +15 -1: maxCharsPerByte +8 -1: checkKey +49 -1: (Ljava/nio/charset/Charset;Lsun/nio/cs/UTF_8$1;)V +80 -1: (Ljava/lang/ClassValue;Ljava/lang/ClassValue$Entry;)Ljava/lang/ClassValue$Entry; +32 -1: Ljava/security/ProtectionDomain; +5 -1: ()TT; +6 -1: insert +10 -1: intersects +38 -1: ([Ljava/lang/Class;Ljava/lang/Class;)V +15 -1: java/lang/Class +12 -1: getPublicKey +37 -1: (ID)Ljava/lang/AbstractStringBuilder; +6 -1: ibm850 +6 -1: locsig +6 -1: ibm852 +19 -1: changeReferenceKind +3 -1: AET +42 -1: (Ljava/util/Collection;Ljava/lang/Class;)V +6 -1: ibm855 +16 -1: getPolicyNoCheck +39 -1: ([B)[[Ljava/lang/annotation/Annotation; +6 -1: ibm857 +10 -1: Error.java +38 -1: ()Ljava/util/List; +14 -1: createInstance +5 -1: cp437 +28 -1: Lsun/util/locale/BaseLocale; +17 -1: getStandardOffset +29 -1: sun/nio/cs/StandardCharsets$1 +36 -1: Ljava/security/ProtectionDomain$Key; +14 -1: ArrayList.java +78 -1: (Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MemberName; +38 -1: java/lang/invoke/MethodHandleImpl$Lazy +42 -1: (Ljava/util/LinkedHashMap$Entry;)V +8 -1: getLongB +7 -1: vmentry +21 -1: lookupExtendedCharset +32 -1: ([TT;)[TT; +53 -1: Ljava/util/concurrent/ConcurrentHashMap$EntrySetView; +6 -1: ibm862 +8 -1: getLongL +32 -1: (Ljava/lang/invoke/MemberName;)J +67 -1: Ljava/lang/Object;Ljava/security/PrivilegedAction; +6 -1: region +6 -1: ibm866 +89 -1: (Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)Lsun/reflect/ConstructorAccessor; +22 -1: java/util/ListIterator +9 -1: wednesday +16 -1: unsuspendThreads +20 -1: Not a Proxy instance +45 -1: Ljava/lang/reflect/InvocationTargetException; +61 -1: (Ljava/lang/CharSequence;II)Ljava/lang/AbstractStringBuilder; +5 -1: ()TV; +32 -1: (Ljava/lang/invoke/MemberName;)V +82 -1: (Ljava/util/jar/JarFile;Ljava/util/jar/JarEntry;)[Ljava/security/cert/Certificate; +34 -1: java/lang/ClassValue$ClassValueMap +32 -1: (Ljava/lang/invoke/MemberName;)Z +15 -1: SPACE_SEPARATOR +17 -1: caseIgnoreCompare +58 -1: (Ljava/lang/Class;)Ljava/lang/invoke/MethodHandles$Lookup; +4 -1: Code +3 -1: AGT +54 -1: (Ljava/lang/StringBuilder;II)Ljava/lang/StringBuilder; +6 -1: ibm874 +15 -1: newMemberBuffer +42 -1: (Ljava/nio/file/Path;)Ljava/nio/file/Path; +33 -1: Ljava/lang/NumberFormatException; +10 -1: Field.java +67 -1: (JLjava/util/function/Function<-TK;+TU;>;)TU; +4 -1: rows +12 -1: MIN_PRIORITY +25 -1: URI has a query component +41 -1: provider security provider debugging +29 -1: sun/nio/cs/ISO_8859_1$Encoder +26 -1: (Ljava/util/zip/ZipFile;)I +26 -1: (Ljava/util/zip/ZipFile;)J +20 -1: Bad digit at end of +29 -1: Ljava/lang/RuntimePermission; +12 -1: initResolved +9 -1: loadFence +13 -1: fieldAccessor +26 -1: (Ljava/util/zip/ZipFile;)V +36 -1: java/lang/CloneNotSupportedException +19 -1: getBasicConstraints +16 -1: putOrderedObject +26 -1: (Ljava/util/zip/ZipFile;)Z +6 -1: target +50 -1: (Ljava/util/concurrent/CountedCompleter;[I[IIIII)V +16 -1: changeReturnType +13 -1: CAUSE_CAPTION +14 -1: checkExactType +50 -1: sun/util/locale/provider/LocaleServiceProviderPool +47 -1: java/lang/invoke/DirectMethodHandle$Constructor +20 -1: CallerSensitive.java +30 -1: java/security/ProtectionDomain +26 -1: java.launcher.opt.vmselect +4 -1: \tat +42 -1: java/util/ArraysParallelSortHelpers$FJLong +39 -1: (Ljava/lang/String;)[Ljava/lang/String; +19 -1: sun.net.www.content +34 -1: ([III)Ljava/util/stream/IntStream; +20 -1: (Ljava/util/Deque;)V +35 -1: (Ljava/lang/reflect/Constructor;)[B +16 -1: WeakHashMap.java +8 -1: ([III)[I +46 -1: (Ljava/util/Properties;Ljava/io/InputStream;)V +54 -1: (I)Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +65 -1: (ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/util/HashMap$Node; +27 -1: URI path component is empty +3 -1: -1- +32 -1: Ljava/io/InterruptedIOException; +9 -1: setLocale +7 -1: [^, ;]* +6 -1: format +61 -1: (Ljava/util/function/Supplier;IZ)Ljava/util/stream/IntStream; +20 -1: getRequestProperties +16 -1: reallocateMemory +28 -1: java/lang/IllegalAccessError +5 -1: query +83 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Class;II)Ljava/lang/invoke/MethodHandle; +7 -1: threadQ +6 -1: STATIC +7 -1: enqueue +21 -1: uninitializedCallSite +3 -1: -2- +26 -1: ()Ljava/util/NavigableSet; +27 -1: getUncaughtExceptionHandler +42 -1: ([Ljava/net/URL;)Ljava/net/URLClassLoader; +30 -1: java/lang/UnsatisfiedLinkError +39 -1: java/util/Collections$ReverseComparator +7 -1: resolve +4 -1: poll +7 -1: (TE;I)V +21 -1: : Unknown launch mode +53 -1: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation; +36 -1: sun.classloader.parentDelegationTime +25 -1: java/net/URLStreamHandler +39 -1: (Ljava/lang/Object;J)Ljava/lang/Object; +53 -1: Ljava/util/Map; +51 -1: java/util/ArraysParallelSortHelpers$FJDouble$Sorter +26 -1: getAnnotatedParameterTypes +18 -1: codePointCountImpl +7 -1: threads +12 -1: offsetBefore +29 -1: ()Ljava/util/Collection; +58 -1: (Lsun/invoke/util/Wrapper;)Ljava/lang/invoke/MethodHandle; +17 -1: DMH.invokeSpecial +3 -1: -3- +16 -1: decodeBufferLoop +43 -1: java/util/concurrent/atomic/AtomicReference +16 -1: reduceKeysToLong +27 -1: newIllegalArgumentException +3 -1: ALL +5 -1: cache +5 -1: queue +4 -1: 8bit +3 -1: -4- +35 -1: Ljava/util/Set; +9 -1: MIN_RADIX +26 -1: ZipFileInflaterInputStream +13 -1: MANIFEST_NAME +18 -1: java/util/TimeZone +175 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;Ljava/lang/invoke/MemberName;Ljava/lang/invoke/MemberName;Ljava/lang/Class;Ljava/lang/invoke/DirectMethodHandle$1;)V +16 -1: getContentLength +11 -1: setDoOutput +22 -1: (Ljava/io/Closeable;)V +13 -1: TimeZone.java +28 -1: sun/misc/ExtensionDependency +6 -1: bindTo +3 -1: -5- +40 -1: ()[Ljava/util/WeakHashMap$Entry; +20 -1: ()Lsun/misc/Cleaner; +9 -1: compareTo +68 -1: java/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask +11 -1: checkedList +14 -1: (ITK;TV;ZZ)TV; +5 -1: greek +3 -1: jar +21 -1: (Ljava/lang/String;)B +21 -1: (Ljava/lang/String;)C +21 -1: (Ljava/lang/String;)D +5 -1: (JS)V +21 -1: (Ljava/lang/String;)F +13 -1: LETTER_NUMBER +14 -1: isAlphaNumeric +21 -1: (Ljava/lang/String;)I +73 -1: (Ljava/nio/charset/Charset;Ljava/lang/String;Ljava/lang/StringCoding$1;)V +21 -1: (Ljava/lang/String;)J +25 -1: makeExactOrGeneralInvoker +3 -1: -6- +25 -1: java/nio/StringCharBuffer +21 -1: Ljava/util/Hashtable; +8 -1: ENQUEUED +8 -1: finalize +22 -1: DirectLongBufferU.java +21 -1: (Ljava/lang/String;)S +10 -1: localhost: +33 -1: isKnownNotToHaveSpecialAttributes +21 -1: (Ljava/lang/String;)V +45 -1: (Ljava/lang/Class<*>;[Ljava/lang/Class<*>;Z)V +21 -1: (Ljava/lang/String;)Z +22 -1: (Ljava/util/Vector;I)V +44 -1: java/nio/charset/UnsupportedCharsetException +23 -1: java/lang/CharacterName +7 -1: checkIO +33 -1: (I)Lsun/misc/URLClassPath$Loader; +90 -1: (Ljava/lang/Class<*>;Ljava/lang/reflect/Constructor<*>;)Ljava/lang/reflect/Constructor<*>; +18 -1: getHeaderFieldDate +9 -1: MIN_VALUE +95 -1: (Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;)Ljava/util/Collection; +44 -1: (Ljava/lang/String;Z)Ljava/util/Enumeration; +8 -1: NOVEMBER +4 -1: gcal +17 -1: getConnectTimeout +124 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; +24 -1: INDEXOFSUBLIST_THRESHOLD +16 -1: isJulianLeapYear +21 -1: reduceEntriesToDouble +15 -1: getPrefixLength +17 -1: is not param at +14 -1: inDaylightTime +39 -1: (Ljava/lang/Class;[I)Ljava/lang/Object; +5 -1: force +98 -1: (Ljava/lang/Class;Lsun/reflect/annotation/AnnotationType;Lsun/reflect/annotation/AnnotationType;)Z +40 -1: (Lsun/reflect/ConstructorAccessorImpl;)V +27 -1: RuntimeInvisibleAnnotations +17 -1: checkTargetChange +9 -1: skipBytes +4 -1: port +25 -1: sun/nio/cs/UTF_16$Encoder +28 -1: MIN_SUPPLEMENTARY_CODE_POINT +4 -1: node +11 -1: not param: +9 -1: debugInit +6 -1: setURL +14 -1: getMonthLength +23 -1: ()Ljava/nio/ByteBuffer; +17 -1: CALENDAR_JAPANESE +11 -1: access$1400 +16 -1: ()Ljava/net/URI; +29 -1: (IZ)Ljava/lang/StringBuilder; +15 -1: Native Library +30 -1: Invalid lambda deserialization +14 -1: throwException +18 -1: nothing to verify! +23 -1: (Ljava/lang/Object;JF)V +3 -1: ART +16 -1: isExtClassLoader +18 -1: Illegal Capacity: +26 -1: java/util/zip/ZipException +4 -1: /../ +34 -1: ([II)Ljava/util/Spliterator$OfInt; +26 -1: (I)Ljava/util/Enumeration; +60 -1: (Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodType; +43 -1: not a field or nested class, no simple type +12 -1: nextPutIndex +15 -1: getConstructor0 +3 -1: AST +11 -1: fromURIPath +49 -1: (Ljava/util/Collections$UnmodifiableCollection;)V +8 -1: makeImpl +51 -1: (Ljava/util/WeakHashMap;Ljava/util/WeakHashMap$1;)V +32 -1: (Ljava/util/function/Supplier;)V +20 -1: namedFunctionInvoker +37 -1: newGetBooleanIllegalArgumentException +19 -1: (Ljava/io/File;ZI)V +8 -1: NULL_KEY +36 -1: Ljava/lang/reflect/Constructor; +21 -1: (Ljava/lang/Object;)B +21 -1: (Ljava/lang/Object;)C +21 -1: (Ljava/lang/Object;)D +21 -1: (Ljava/lang/Object;)F +30 -1: ()Lsun/util/locale/BaseLocale; +21 -1: (Ljava/lang/Object;)I +21 -1: (Ljava/lang/Object;)J +10 -1: lineNumber +95 -1: (JLjava/util/function/ToDoubleBiFunction<-TK;-TV;>;DLjava/util/function/DoubleBinaryOperator;)D +16 -1: CoderResult.java +44 -1: (Ljava/util/NavigableSet;Ljava/lang/Class;)V +21 -1: (Ljava/lang/Object;)S +13 -1: getNameString +129 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;Ljava/lang/invoke/MemberName;Ljava/lang/invoke/DirectMethodHandle$1;)V +21 -1: (Ljava/lang/Object;)V +21 -1: (Ljava/lang/Object;)Z +81 -1: Ljava/util/HashMap;>; +49 -1: java/util/concurrent/locks/ReentrantLock$FairSync +11 -1: csisolatin0 +11 -1: csisolatin1 +7 -1: isSpace +10 -1: getDefault +11 -1: csisolatin2 +16 -1: ()Ljava/net/URL; +11 -1: csisolatin4 +14 -1: invokeExact_MT +11 -1: csisolatin5 +28 -1: (Ljava/io/FileInputStream;)V +11 -1: csisolatin9 +8 -1: isLetter +15 -1: getConstructors +21 -1: mainAppContextDefault +29 -1: ()[Ljava/lang/reflect/Method; +23 -1: Ljava/util/WeakHashMap; +12 -1: LF_INVSTATIC +17 -1: DirectBuffer.java +10 -1: newEncoder +10 -1: getVersion +32 -1: java/lang/IllegalAccessException +20 -1: java/util/Collection +61 -1: (Ljava/util/concurrent/ConcurrentHashMap;Ljava/lang/Object;)V +19 -1: $deserializeLambda$ +8 -1: removeIf +25 -1: sun/reflect/FieldAccessor +129 -1: ;>(Ljava/util/function/Function<-TT;+TU;>;Ljava/util/Comparator<-TU;>;)Ljava/util/Comparator; +17 -1: parseAbsoluteSpec +37 -1: ([Ljava/util/HashMap$Node;I)V +17 -1: java/util/HashSet +13 -1: spreadInvoker +20 -1: suppressAccessChecks +32 -1: Ljava/lang/InterruptedException; +11 -1: oldMappings +9 -1: lookupTag +16 -1: java/lang/System +5 -1: LFI: +6 -1: IBM737 +9 -1: SHORT_IDS +45 -1: ([IIILjava/util/function/IntBinaryOperator;)V +20 -1: getMetaInfEntryNames +10 -1: isReadOnly +50 -1: ()Ljava/util/SortedSet; +12 -1: java.vm.name +30 -1: java/lang/Class$AnnotationData +61 -1: (ILjava/lang/invoke/LambdaForm;)Ljava/lang/invoke/LambdaForm; +7 -1: address +44 -1: (Ljava/util/function/BiConsumer<-TK;-TV;>;)V +58 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;I)V +112 -1: (Ljava/lang/Object;TV;Ljava/lang/ref/ReferenceQueue;ILjava/util/WeakHashMap$Entry;)V +14 -1: aliases_KOI8_R +3 -1: AWT +14 -1: aliases_KOI8_U +24 -1: ARRAY_DOUBLE_BASE_OFFSET +23 -1: Ljava/util/jar/JarFile; +91 -1: (Ljava/lang/Class;[Ljava/lang/Class<*>;[Ljava/lang/Class<*>;IILjava/lang/String;[B[B)V +14 -1: mappingAddress +19 -1: [Ljava/lang/Object; +17 -1: sun/misc/JarIndex +9 -1: image/jpg +49 -1: (Ljava/lang/String;I)Lsun/util/calendar/ZoneInfo; +37 -1: java/lang/invoke/DirectMethodHandle$1 +34 -1: java/util/Collections$SingletonMap +89 -1: (JLjava/util/function/ToIntBiFunction<-TK;-TV;>;ILjava/util/function/IntBinaryOperator;)I +46 -1: (Ljava/util/Comparator;)Ljava/util/Comparator; +11 -1: isTitleCase +38 -1: java/lang/IllegalMonitorStateException +33 -1: java/nio/BufferUnderflowException +28 -1: java/lang/ClassValue$Version +11 -1: printLocale +13 -1: STORE_BARRIER +42 -1: ([ILjava/util/function/IntUnaryOperator;)V +26 -1: sun/util/locale/BaseLocale +29 -1: java/io/ObjectStreamException +41 -1: sun/reflect/UnsafeStaticFieldAccessorImpl +60 -1: ([Ljava/lang/Object;Ljava/util/Iterator;)[Ljava/lang/Object; +30 -1: (Ljava/nio/charset/Charset;)[B +73 -1: ([Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process; +3 -1: VST +80 -1: Java(TM) SE Runtime Environment (build 1.8.0-internal-iklam_2013_11_27_21_25-b00 +85 -1: (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/net/URLStreamHandler;)V +20 -1: getStackTraceElement +36 -1: java/util/LinkedHashMap$LinkedKeySet +17 -1: getNormalizedYear +15 -1: maxBytesPerChar +16 -1: java/util/Random +34 -1: (I[C)Ljava/lang/invoke/LambdaForm; +11 -1: nbits < 0: +7 -1: H_PCHAR +29 -1: (Ljava/nio/charset/Charset;)I +36 -1: (I[I[C)Ljava/lang/invoke/LambdaForm; +23 -1: java/lang/ClassLoader$1 +23 -1: java/lang/ClassLoader$2 +23 -1: java/lang/ClassLoader$3 +9 -1: sizeTable +36 -1: (Z)Ljava/lang/AbstractStringBuilder; +29 -1: (Ljava/nio/charset/Charset;)V +25 -1: ARRAY_BOOLEAN_INDEX_SCALE +29 -1: (Ljava/nio/charset/Charset;)Z +6 -1: keySet +20 -1: declaredConstructors +25 -1: oracle/jrockit/jfr/Timing +12 -1: sizeIsSticky +6 -1: IBM775 +17 -1: currentTimeMillis +28 -1: java/nio/DirectDoubleBufferS +71 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/invoke/MethodType;B)V +28 -1: java/nio/DirectDoubleBufferU +19 -1: cachedFixedDateJan1 +15 -1: getClassContext +65 -1: (Ljava/security/CodeSource;Ljava/security/PermissionCollection;)V +16 -1: unmodifiableList +10 -1: getDoubleB +82 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/String; +11 -1: getEntryCrc +10 -1: getDoubleL +20 -1: (C)Ljava/lang/Class; +11 -1: Null action +22 -1: java/io/BufferedWriter +67 -1: (Ljava/lang/String;[Ljava/lang/Class<*>;)Ljava/lang/reflect/Method; +22 -1: parseSelectAnnotations +6 -1: rename +20 -1: acquireFieldAccessor +43 -1: (Ljava/util/Vector;[Ljava/lang/Object;III)V +32 -1: Ljava/lang/NullPointerException; +29 -1: (Ljava/lang/ThreadLocal<*>;)V +18 -1: descendingIterator +37 -1: java/util/Collections$SynchronizedSet +24 -1: mark/reset not supported +12 -1: ) > toIndex( +13 -1: <> +10 -1: fastRemove +4 -1: load +31 -1: sun/reflect/ReflectionFactory$1 +39 -1: (Ljava/util/List<*>;)Ljava/lang/Object; +39 -1: Ljava/util/Map; +9 -1: offerLast +31 -1: ()Ljava/lang/invoke/MethodType; +40 -1: Ljava/lang/Object; +17 -1: getObjectVolatile +14 -1: suspendThreads +55 -1: (Ljava/lang/String;ZLjava/util/Set;)Lsun/misc/Resource; +75 -1: (Ljava/util/List<+Ljava/lang/Comparable<-TT;>;>;TT;)I +6 -1: Lookup +20 -1: java/io/OutputStream +41 -1: Could not create application class loader +28 -1: Lsun/misc/JavaUtilJarAccess; +46 -1: java/util/Collections$SynchronizedNavigableSet +8 -1: override +21 -1: threadLocalRandomSeed +10 -1: TEXT_PLAIN +22 -1: ([B)Ljava/lang/String; +29 -1: java/nio/InvalidMarkException +14 -1: Throwable.java +27 -1: newWrongMethodTypeException +6 -1: ptypes +8 -1: bugLevel +62 -1: (ILjava/lang/CharSequence;II)Ljava/lang/AbstractStringBuilder; +37 -1: ()Ljava/util/Locale$LocaleNameGetter; +14 -1: getEntryMethod +7 -1: getByte +12 -1: UTF-32BE-BOM +4 -1: lock +34 -1: java/security/AccessControlContext +79 -1: (Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/MemberName; +5 -1: DEBUG +5 -1: unbox +17 -1: CLASSPATH_OPTOSFT +4 -1: cbrt +21 -1: LocalizedObjectGetter +21 -1: ProtectionDomain.java +22 -1: ([J)Ljava/util/BitSet; +17 -1: getUnresolvedName +34 -1: (Ljava/util/Map;Ljava/util/Map;I)V +7 -1: cskoi8r +14 -1: getInterfaces0 +48 -1: (Lsun/net/www/MessageHeader;)[Ljava/lang/String; +14 -1: getFileNameMap +16 -1: preserveCombiner +19 -1: getDefaultUseCaches +57 -1: (Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class; +21 -1: (D)Ljava/lang/Double; +15 -1: iso8859_15_fdis +23 -1: java/util/regex/Pattern +6 -1: ibm912 +14 -1: findBuiltinLib +42 -1: java/lang/annotation/AnnotationFormatError +6 -1: ibm914 +6 -1: ibm915 +44 -1: java/nio/charset/IllegalCharsetNameException +22 -1: COMBINING_SPACING_MARK +20 -1: ()Ljava/lang/Thread; +8 -1: readLine +12 -1: (unresolved +65 -1: (Ljava/lang/String;Z)Ljava/util/Enumeration; +41 -1: ([Ljava/lang/String;[Ljava/lang/String;)V +30 -1: java/lang/Class$ReflectionData +8 -1: requests +52 -1: (Ljava/nio/charset/Charset;Lsun/nio/cs/US_ASCII$1;)V +12 -1: ACCESS_WRITE +6 -1: ibm920 +12 -1: CR_ERROR_MIN +6 -1: jarMap +6 -1: ibm923 +15 -1: java/lang/Error +11 -1: VM_SETTINGS +18 -1: name can't be null +7 -1: PRESENT +19 -1: setSecurityManager0 +101 -1: (Ljava/nio/channels/WritableByteChannel;Ljava/nio/charset/CharsetEncoder;I)Lsun/nio/cs/StreamEncoder; +25 -1: ()Ljava/util/jar/JarFile; +26 -1: java/io/ObjectOutputStream +13 -1: no !/ in spec +5 -1: (II)C +12 -1: setPriority0 +30 -1: (Z)[Ljava/lang/reflect/Method; +28 -1: sun/nio/cs/ThreadLocalCoders +5 -1: (II)I +22 -1: java/io/BufferedReader +26 -1: ()Lsun/misc/JavaNetAccess; +10 -1: Asia/Dhaka +14 -1: parallelStream +5 -1: (II)V +5 -1: (II)Z +31 -1: Ljava/lang/reflect/Constructor; +21 -1: ()Ljava/time/Instant; +31 -1: (Ljava/lang/String;III[J[I[IZ)V +8 -1: Volatile +23 -1: isUnicodeIdentifierPart +27 -1: longPrimitiveParameterCount +16 -1: Map is non-empty +24 -1: getLocalizedOutputStream +14 -1: java/lang/Byte +10 -1: staticBase +11 -1: lastElement +17 -1: replaceStaleEntry +17 -1: MAX_LOW_SURROGATE +28 -1: java.launcher.X.macosx.usage +20 -1: registerShutdownHook +16 -1: SECOND_IN_MILLIS +8 -1: Embedded +16 -1: BootstrapMethods +14 -1: numInvocations +79 -1: (Ljava/util/Collection;)Ljava/util/Enumeration; +10 -1: rotateLeft +46 -1: ([Ljava/lang/Object;)Ljava/util/stream/Stream; +6 -1: verify +17 -1: OTHER_PUNCTUATION +26 -1: acquireConstructorAccessor +38 -1: (Ljava/lang/String;I)Ljava/lang/Class; +30 -1: java/net/UnknownContentHandler +20 -1: PREFIX_LENGTH_OFFSET +12 -1: nextGetIndex +14 -1: standardOffset +10 -1: entryNames +15 -1: application/xml +3 -1: BET +39 -1: ([DIII)Ljava/util/Spliterator$OfDouble; +83 -1: (JLjava/util/function/BiFunction;Ljava/util/function/BiFunction;)Ljava/lang/Object; +10 -1: initMethod +47 -1: (Ljava/util/LinkedList$Node;)Ljava/lang/Object; +8 -1: isSealed +12 -1: isAccessible +11 -1: audio/x-wav +46 -1: (Ljava/lang/String;)Ljava/util/jar/Attributes; +24 -1: ()Ljava/io/OutputStream; +15 -1: FIELD_MODIFIERS +30 -1: sun/misc/URLClassPath$Loader$1 +20 -1: recursive invocation +34 -1: (Ljava/lang/String;)Ljava/net/URL; +12 -1: linkNodeLast +34 -1: call site initialization exception +17 -1: casAnnotationType +8 -1: x-ibm874 +7 -1: isUpper +58 -1: java/util/concurrent/ConcurrentHashMap$MapReduceValuesTask +31 -1: Ill-formed Unicode locale key: +12 -1: defineClass0 +12 -1: defineClass1 +12 -1: defineClass2 +59 -1: Can not call newInstance() on the Class for java.lang.Class +10 -1: codePoints +3 -1: ... +14 -1: readAheadLimit +14 -1: parallelSetAll +41 -1: ([Ljava/lang/Object;I)[Ljava/lang/Object; +148 -1: (Ljava/lang/Throwable$PrintStreamOrWriter;[Ljava/lang/StackTraceElement;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V +10 -1: Deque.java +21 -1: Must be volatile type +7 -1: setForm +58 -1: Ljava/lang/Number;Ljava/lang/Comparable; +47 -1: (Ljava/lang/String;Ljava/security/CodeSource;)V +30 -1: java/io/InterruptedIOException +44 -1: java/util/Collections$SynchronizedCollection +16 -1: Invalid Jar file +32 -1: sun/util/calendar/CalendarSystem +67 -1: (JLsun/util/calendar/CalendarDate;)Lsun/util/calendar/CalendarDate; +19 -1: DEFAULT_BUFFER_SIZE +16 -1: readObjectNoData +16 -1: setJavaNioAccess +73 -1: (Ljava/lang/invoke/LambdaForm$Name;[Ljava/lang/Object;)Ljava/lang/Object; +14 -1: copyToIntArray +10 -1: hasWaiters +20 -1: (I)Ljava/lang/Class; +35 -1: all turn on all debugging +14 -1: Invalid host: +26 -1: Lsun/nio/cs/StreamEncoder; +43 -1: sun/misc/JavaSecurityProtectionDomainAccess +11 -1: getNamedCon +8 -1: H_SERVER +27 -1: java/util/function/Consumer +12 -1: isLocalClass +81 -1: (Ljava/util/LinkedHashMap$Entry;Ljava/util/LinkedHashMap$Entry;)V +83 -1: Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Comparable; +4 -1: exec +43 -1: java/lang/reflect/InvocationTargetException +35 -1: (Ljava/io/File;Ljava/lang/String;)V +9 -1: modifiers +35 -1: (Ljava/io/File;Ljava/lang/String;)Z +9 -1: Byte.java +12 -1: unknown mode +18 -1: initializeVerifier +24 -1: (Ljava/nio/ByteBuffer;)I +22 -1: ([Ljava/lang/Object;)I +11 -1: correctType +6 -1: escape +52 -1: (Ljava/security/ProtectionDomain;)Ljava/lang/String; +11 -1: annotations +121 -1: (Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName; +22 -1: using an instance of +14 -1: getSpeciesData +28 -1: ()Ljava/security/CodeSource; +12 -1: JZENTRY_NAME +24 -1: (Ljava/nio/ByteBuffer;)V +4 -1: ZBSC +22 -1: ([Ljava/lang/Object;)V +7 -1: isParam +165 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +70 -1: (ILjava/util/List;>;)Ljava/lang/invoke/LambdaForm; +24 -1: Ljava/io/FilePermission; +22 -1: ([Ljava/lang/Object;)Z +11 -1: mergeHeader +11 -1: applyAsLong +28 -1: (IJ)Ljava/lang/StringBuffer; +10 -1: arityCheck +52 -1: (ILjava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +13 -1: toUpperCaseEx +9 -1: nextIndex +11 -1: start > end +4 -1: long +6 -1: Static +27 -1: ()Ljava/lang/reflect/Field; +10 -1: bufUpdater +43 -1: averageBytesPerChar exceeds maxBytesPerChar +105 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lsun/util/locale/BaseLocale$1;)V +23 -1: ARRAY_SHORT_INDEX_SCALE +15 -1: getHeaderFields +36 -1: java/util/HashMap$HashMapSpliterator +10 -1: Guard.java +29 -1: java/util/RandomAccessSubList +6 -1: addAll +7 -1: getTime +16 -1: invokeHandleForm +32 -1: sun/util/locale/LocaleExtensions +16 -1: checkAndLoadMain +19 -1: INTERFACE_MODIFIERS +11 -1: resolveName +20 -1: getContentLengthLong +53 -1: (ICLjava/lang/Object;)Ljava/lang/invoke/MethodHandle; +19 -1: name cannot be null +23 -1: hasReceiverTypeDispatch +12 -1: getExtension +49 -1: Ljava/util/Set; +114 -1: (Ljava/lang/String;[J[I[J[I[Lsun/util/calendar/ZoneInfoFile$ZoneOffsetTransitionRule;)Lsun/util/calendar/ZoneInfo; +24 -1: NativeSignalHandler.java +58 -1: (Ljava/lang/Thread;)Ljava/lang/ThreadLocal$ThreadLocalMap; +10 -1: interface +68 -1: (Ljava/lang/String;)Ljava/lang/invoke/BoundMethodHandle$SpeciesData; +15 -1: addShutdownHook +32 -1: java/security/AccessController$1 +10 -1: filterTags +19 -1: [Ljava/lang/Number; +92 -1: (Ljava/util/function/ToLongFunction<-TT;>;)Ljava/util/Comparator; +43 -1: java/util/LinkedHashMap$LinkedEntryIterator +5 -1: utf-8 +11 -1: iso-8859-13 +11 -1: iso-8859-15 +58 -1: (Lsun/misc/URLClassPath$JarLoader;)Ljava/util/jar/JarFile; +41 -1: CertPathValidator debugging +22 -1: ARRAY_LONG_BASE_OFFSET +57 -1: (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; +13 -1: queuePrintJob +14 -1: Watchable.java +15 -1: jdkMajorVersion +62 -1: (Ljava/lang/String;ZJJ)Ljava/lang/management/MemoryPoolMXBean; +23 -1: twoToTheDoubleScaleDown +22 -1: registerVMNotification +30 -1: ()Lsun/misc/JavaUtilJarAccess; +17 -1: getTargetVolatile +4 -1: exit +13 -1: StringDecoder +12 -1: hasRemaining +9 -1: bigEndian +14 -1: checkMulticast +13 -1: clearProperty +18 -1: ForEachMappingTask +15 -1: Collection.java +55 -1: (Ljava/io/InputStream;)Ljava/security/cert/Certificate; +5 -1: UTF-8 +11 -1: transitions +7 -1: wrapAlt +27 -1: ClassNotFoundException.java +20 -1: UnresolvedPermission +14 -1: charsetForName +9 -1: getParent +18 -1: [Ljava/lang/Short; +24 -1: UnmodifiableNavigableMap +5 -1: xflow +10 -1: interfaces +19 -1: doubleToRawLongBits +73 -1: (Ljava/lang/reflect/Constructor<*>;[Ljava/lang/Object;)Ljava/lang/Object; +10 -1: getInCheck +21 -1: (Ljava/lang/Thread;)V +15 -1: fromIndex < 0: +63 -1: (ITK;TV;Ljava/util/concurrent/ConcurrentHashMap$Node;)V +9 -1: pollFirst +21 -1: (Ljava/lang/Thread;)Z +16 -1: checkProxyMethod +39 -1: generateLambdaFormInterpreterEntryPoint +15 -1: findLoadedClass +6 -1: system +5 -1: ITALY +45 -1: combiner SubjectDomainCombiner debugging +34 -1: NativeConstructorAccessorImpl.java +22 -1: ([C)Ljava/lang/String; +39 -1: (Ljava/lang/String;Ljava/lang/Class;Z)V +18 -1: java/lang/Thread$1 +20 -1: window can't be null +10 -1: Debug.java +17 -1: singletonIterator +53 -1: java/util/concurrent/ConcurrentHashMap$ForEachKeyTask +20 -1: java/security/Policy +13 -1: getDescriptor +32 -1: (I)Ljava/lang/invoke/MethodType; +15 -1: nativeLibraries +27 -1: sun/util/locale/LanguageTag +8 -1: priority +12 -1: IntegerCache +14 -1: connectTimeout +9 -1: namePairs +17 -1: vmAllowSuspension +16 -1: METHOD_MODIFIERS +51 -1: (Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +20 -1: MIN_TREEIFY_CAPACITY +13 -1: getEntryBytes +33 -1: ()Lsun/reflect/ReflectionFactory; +17 -1: getDisplayCountry +13 -1: isWrapperType +5 -1: utf16 +12 -1: parallelSort +27 -1: (Ljava/nio/ByteBuffer;IIZ)V +56 -1: (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;I)Z +9 -1: isDefined +20 -1: sun/misc/FloatConsts +10 -1: putDoubleB +30 -1: java/lang/NoSuchFieldException +27 -1: Value out of range. Value:" +36 -1: sun/reflect/NativeMethodAccessorImpl +7 -1: decoder +38 -1: ([Ljava/lang/invoke/MutableCallSite;)V +10 -1: putDoubleL +68 -1: (Ljava/lang/reflect/Method;)Lsun/reflect/generics/scope/MethodScope; +37 -1: java/lang/invoke/MethodHandles$Lookup +9 -1: Void.java +28 -1: sun/util/locale/BaseLocale$1 +10 -1: stackTrace +7 -1: toClass +11 -1: access$1500 +41 -1: (Ljava/lang/Object;I)Ljava/lang/Class<*>; +148 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;Ljava/lang/invoke/MemberName;Ljava/lang/Object;JLjava/lang/invoke/DirectMethodHandle$1;)V +22 -1: ARRAY_BYTE_BASE_OFFSET +13 -1: ZipEntry.java +56 -1: (Ljava/util/List;Ljava/util/Collection;)Ljava/util/List; +5 -1: utf32 +16 -1: ISO_646.irv:1991 +5 -1: p-126 +20 -1: sun.net.www.protocol +3 -1: key +20 -1: IMPLEMENTATION_TITLE +93 -1: (Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)Lsun/util/locale/LanguageTag; +66 -1: ([Ljava/lang/Object;[Ljava/lang/Object;IIILjava/util/Comparator;)V +27 -1: java/nio/DirectFloatBufferS +27 -1: java/nio/DirectFloatBufferU +15 -1: JZENTRY_COMMENT +8 -1: casTabAt +10 -1: getVariant +24 -1: Ljava/lang/Thread$State; +35 -1: ()Ljava/lang/AbstractStringBuilder; +114 -1: (Ljava/security/CodeSource;Ljava/security/PermissionCollection;Ljava/lang/ClassLoader;[Ljava/security/Principal;)V +16 -1: getShortVolatile +18 -1: SoftReference.java +3 -1: BST +12 -1: isCastableTo +28 -1: sun.zip.disableMemoryMapping +11 -1: copyOfRange +17 -1: ()Lsun/misc/Perf; +59 -1: (Ljava/lang/String;[Ljava/io/File;Ljava/lang/ClassLoader;)V +27 -1: (Lsun/misc/JavaAWTAccess;)V +8 -1: DECLARED +18 -1: loadedLibraryNames +6 -1: CENNAM +7 -1: encprop +5 -1: ABASE +27 -1: java/util/WeakHashMap$Entry +13 -1: wrapWithPrims +5 -1: UTF32 +29 -1: Ljava/net/URISyntaxException; +6 -1: groups +65 -1: (Ljava/util/Set<+TT;>;)Ljava/util/Set; +32 -1: lambda$comparingByKey$6d558cbf$1 +15 -1: removeElementAt +49 -1: [Ljava/util/concurrent/ConcurrentHashMap$Segment; +32 -1: Sign character in wrong position +6 -1: IBM819 +39 -1: java/security/cert/CertificateException +4 -1: join +30 -1: Ljava/lang/invoke/ForceInline; +14 -1: expandCapacity +19 -1: Ljava/lang/Integer; +11 -1: NUMBER_THAI +10 -1: getExtURLs +9 -1: retainAll +21 -1: (S)Ljava/lang/String; +8 -1: truncate +51 -1: java/util/ArraysParallelSortHelpers$FJObject$Sorter +28 -1: newIndexOutOfBoundsException +26 -1: JavaUtilJarAccessImpl.java +22 -1: (II)Ljava/util/BitSet; +10 -1: getLongAt0 +65 -1: (Ljava/lang/Class;)TA; +26 -1: (Ljava/lang/ThreadLocal;)I +5 -1: (J)[B +27 -1: Ljava/lang/CharacterData00; +18 -1: sun/misc/Cleaner$1 +59 -1: (Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;)I +114 -1: (JLjava/util/function/ToDoubleFunction;>;DLjava/util/function/DoubleBinaryOperator;)D +28 -1: java/lang/ClassCastException +26 -1: (Ljava/lang/ThreadLocal;)V +27 -1: ()[Ljava/lang/reflect/Type; +13 -1: not invoker: +56 -1: (Ljava/net/URL;Ljava/net/Proxy;)Ljava/net/URLConnection; +6 -1: before +37 -1: ([DII)Ljava/util/stream/DoubleStream; +9 -1: logicalOr +9 -1: IS_METHOD +12 -1: SPACE_USABLE +12 -1: lastModified +10 -1: setSigners +8 -1: Invokers +7 -1: nCopies +12 -1: utf-32le-bom +7 -1: (IIII)J +17 -1: jdkSpecialVersion +26 -1: ()Ljava/lang/StringBuffer; +17 -1: SearchEntriesTask +14 -1: java/net/Parts +20 -1: Ljava/lang/Runnable; +35 -1: java/util/WeakHashMap$ValueIterator +19 -1: FinalReference.java +7 -1: (IIII)V +23 -1: Ljava/lang/ThreadGroup; +10 -1: nullsFirst +8 -1: setCache +55 -1: (Ljava/util/List;Ljava/lang/Object;Ljava/lang/Object;)Z +24 -1: java/util/SimpleTimeZone +6 -1: IBM850 +6 -1: IBM852 +25 -1: sun/net/www/MeteredStream +4 -1: exts +6 -1: IBM855 +16 -1: allocateElements +6 -1: IBM857 +19 -1: setDefaultUseCaches +6 -1: IBM858 +5 -1: slice +9 -1: marklimit +77 -1: Ljava/lang/Object;Ljava/security/PrivilegedExceptionAction; +32 -1: java/util/Collections$CheckedSet +12 -1: getModifiers +8 -1: protocol +10 -1: getInteger +33 -1: ([J)Ljava/util/stream/LongStream; +6 -1: IBM862 +8 -1: Map.java +35 -1: java/lang/Class$EnclosingMethodInfo +25 -1: (J)Ljava/math/BigInteger; +31 -1: (Ljava/net/URL;Ljava/io/File;)V +6 -1: IBM866 +6 -1: unload +28 -1: sun/invoke/util/VerifyAccess +105 -1: ()Ljava/util/Map;Ljava/lang/annotation/Annotation;>; +25 -1: Resetting to invalid mark +20 -1: java/util/Vector$Itr +5 -1: SHIFT +11 -1: NonfairSync +18 -1: getSecurityManager +34 -1: ()[Ljava/lang/ClassValue$Entry<*>; +28 -1: (J)Ljava/lang/StringBuilder; +28 -1: (Ljava/security/PublicKey;)V +12 -1: getResources +6 -1: IBM874 +27 -1: which Java does not define +36 -1: (Ljava/lang/invoke/MethodTypeForm;)V +48 -1: array length is not legal for long[] or double[] +18 -1: IS_FIELD_OR_METHOD +7 -1: Aliases +17 -1: checkedExceptions +13 -1: getDayOfMonth +51 -1: (Ljava/util/Spliterator;Z)Ljava/util/stream/Stream; +20 -1: java/io/EOFException +26 -1: Enclosing method not found +17 -1: flushLeftoverChar +122 -1: (Ljava/lang/Class<*>;[Ljava/lang/Class<*>;[Ljava/lang/Class<*>;IILjava/lang/String;[B[B)Ljava/lang/reflect/Constructor<*>; +18 -1: buildAnnotatedType +21 -1: setContextClassLoader +22 -1: java/io/UnixFileSystem +20 -1: nonSyncContentEquals +43 -1: java/util/Collections$SynchronizedSortedMap +15 -1: Properties.java +35 -1: com.oracle.usagetracker.config.file +13 -1: java/util/Map +18 -1: setEagerValidation +13 -1: getSetMessage +6 -1: unlock +14 -1: refKindIsField +22 -1: bad field type alias: +17 -1: casAnnotationData +6 -1: AUGUST +106 -1: (Ljava/util/concurrent/CountedCompleter;[Ljava/lang/Object;[Ljava/lang/Object;IIIILjava/util/Comparator;)V +11 -1: monitorExit +17 -1: linkMethodTracing +69 -1: (Ljava/lang/String;Ljava/lang/String;Lsun/util/locale/BaseLocale$1;)V +21 -1: java/lang/ClassLoader +39 -1: PKCS11 KeyStore debugging +10 -1: checkRtype +25 -1: getLocalGregorianCalendar +23 -1: GenericDeclaration.java +12 -1: isViewableAs +22 -1: static_oop_field_count +72 -1: (Ljava/util/function/ToDoubleFunction<-TT;>;)Ljava/util/Comparator; +11 -1: languageKey +6 -1: Class +34 -1: java/util/HashMap$ValueSpliterator +37 -1: (IJ)Ljava/lang/AbstractStringBuilder; +17 -1: privilegedContext +36 -1: java/util/LinkedHashMap$LinkedValues +11 -1: getHostName +10 -1: beginEntry +7 -1: isAlpha +61 -1: (Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/LambdaForm; +10 -1: expandArgs +14 -1: Finalizer.java +14 -1: timeDefinition +28 -1: ()Ljava/util/jar/Attributes; +14 -1: ansi_x3.4-1968 +11 -1: setPriority +23 -1: (C)Ljava/lang/Class<*>; +26 -1: (Ljava/lang/Object;TV;)TV; +70 -1: (Ljava/util/function/BiFunction;Ljava/lang/Object;Ljava/lang/Object;)V +48 -1: ()Lsun/reflect/generics/factory/GenericsFactory; +25 -1: java/lang/invoke/CallSite +8 -1: tzdb.dat +17 -1: containsAllLimits +17 -1: fileNameMapLoaded +6 -1: values +17 -1: setLastAccessTime +12 -1: expandFromVM +50 -1: java/lang/invoke/MethodHandle$PolymorphicSignature +3 -1: .EC +14 -1: access denied +22 -1: java/util/AbstractList +47 -1: (IILjava/lang/String;)Ljava/lang/StringBuilder; +52 -1: ()Lsun/reflect/generics/repository/MethodRepository; +22 -1: (Ljava/lang/String;)[B +57 -1: (Ljava/lang/Object;)Ljava/lang/invoke/DirectMethodHandle; +18 -1: compareAndSwapLong +4 -1: != +6 -1: StdArg +29 -1: (Ljava/security/Permission;)V +22 -1: ([D)Ljava/lang/String; +28 -1: Lsun/reflect/MethodAccessor; +14 -1: ansi_x3.4-1986 +20 -1: getPeakFinalRefCount +29 -1: (Ljava/security/Permission;)Z +5 -1: debug +38 -1: (Ljava/lang/reflect/Constructor<*>;)[B +27 -1: java/util/GregorianCalendar +16 -1: Null replacement +26 -1: ()Ljava/lang/reflect/Type; +28 -1: DIRECTIONALITY_LEFT_TO_RIGHT +102 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lsun/util/locale/BaseLocale; +15 -1: isConvertibleTo +24 -1: ARRAY_DOUBLE_INDEX_SCALE +16 -1: getComponentType +29 -1: sun/util/locale/LocaleMatcher +11 -1: LOCALECACHE +6 -1: UNWRAP +16 -1: AbstractSet.java +3 -1: CAT +36 -1: java/lang/annotation/RetentionPolicy +14 -1: getParameters0 +8 -1: .Handler +33 -1: Ljava/lang/IllegalStateException; +10 -1: RAW_RETURN +20 -1: java/lang/ClassValue +16 -1: getDisplayString +152 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;I)Ljava/util/concurrent/ConcurrentHashMap$Node; +67 -1: ()Ljava/util/Map; +214 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +33 -1: java/lang/invoke/SerializedLambda +42 -1: ([Ljava/lang/Object;II)[Ljava/lang/Object; +22 -1: java/util/zip/ZipUtils +9 -1: setDaemon +26 -1: java/net/HttpURLConnection +6 -1: mkdirs +20 -1: (Ljava/io/Reader;I)V +28 -1: (IC)Ljava/lang/StringBuffer; +45 -1: ([Ljava/lang/Class<*>;I)[Ljava/lang/Class<*>; +29 -1: java/lang/invoke/MethodHandle +28 -1: sun/misc/CompoundEnumeration +6 -1: setVal +23 -1: INTERNED_ARGUMENT_LIMIT +4 -1: NULL +49 -1: (Ljava/lang/invoke/MemberName;Ljava/lang/Class;)Z +43 -1: java/util/Collections$UnmodifiableSortedMap +39 -1: (Ljava/lang/Object;Ljava/lang/Object;)I +6 -1: ([JJ)I +19 -1: java/io/PrintWriter +25 -1: ()Ljava/lang/ThreadGroup; +5 -1: (IJ)J +16 -1: onMalformedInput +15 -1: decrementAndGet +11 -1: -2147483648 +6 -1: reduce +12 -1: asCharBuffer +39 -1: (Ljava/lang/Object;Ljava/lang/Object;)V +44 -1: (Ljava/util/SortedSet;)Ljava/util/SortedSet; +9 -1: backtrace +3 3: Bar +47 -1: ()Lsun/misc/JavaSecurityProtectionDomainAccess; +39 -1: (Ljava/lang/Object;Ljava/lang/Object;)Z +5 -1: (IJ)V +6 -1: ([JJ)V +22 -1: ([Ljava/lang/Thread;)I +5 -1: (IJ)Z +7 -1: ([BII)I +79 -1: (Ljava/util/Comparator<-TT;>;)Ljava/util/Comparator; +12 -1: getUnchecked +10 -1: getBaseURL +36 -1: (Ljava/lang/Object;)Ljava/util/List; +53 -1: (Ljava/util/function/Function;)Ljava/util/Comparator; +10 -1: getComment +7 -1: ([BII)V +30 -1: privateGetDeclaredConstructors +58 -1: (Ljava/lang/String;ZILjava/util/Locale;)Ljava/lang/String; +18 -1: unknown era name: +13 -1: invokeSpecial +9 -1: checkLink +16 -1: cspc8codepage437 +6 -1: stream +18 -1: sun/nio/cs/UTF_8$1 +18 -1: contextClassLoader +50 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;I)V +30 -1: sun/util/calendar/BaseCalendar +11 -1: enumeration +18 -1: key can't be empty +137 -1: (JLjava/util/function/Function;+TU;>;Ljava/util/function/BiFunction<-TU;-TU;+TU;>;)TU; +10 -1: getBoolean +5 -1: eetop +49 -1: (Ljava/lang/invoke/MethodType;)Ljava/lang/String; +43 -1: sun/reflect/generics/scope/ConstructorScope +13 -1: CANADA_FRENCH +39 -1: Ljava/nio/channels/ReadableByteChannel; +15 -1: java/lang/Float +29 -1: DIRECTIONALITY_OTHER_NEUTRALS +52 -1: (ZLjava/nio/charset/Charset;Ljava/io/OutputStream;)V +8 -1: appendTo +19 -1: PARAGRAPH_SEPARATOR +16 -1: (Unknown Source) +4 -1: tree +38 -1: (I[C)Ljava/lang/AbstractStringBuilder; +14 -1: VerifierStream +48 -1: (Ljava/util/Collection;Ljava/lang/Object;)V +15 -1: releaseInflater +20 -1: getHeaderNamesInList +17 -1: getSystemPackages +8 -1: teardown +6 -1: (BZI)I +10 -1: checkWrite +19 -1: JavaLangAccess.java +31 -1: Ljava/lang/ClassValue$Identity; +50 -1: (Ljava/util/concurrent/CountedCompleter;[S[SIIII)V +24 -1: getDeclaredConstructors0 +3 -1: /.. +3 -1: /./ +16 -1: hashCodeForCache +18 -1: Property settings: +26 -1: Illegal initial capacity: +10 -1: text/plain +61 -1: (Ljava/util/function/ToDoubleFunction;)Ljava/util/Comparator; +24 -1: createMemoryManagerMBean +10 -1: ,lastRule= +9 -1: GMT-00:00 +5 -1: mtime +40 -1: (Ljava/lang/String;I)[Ljava/lang/String; +11 -1: (TT;TV;)TV; +154 -1: (Ljava/lang/Class<*>;Ljava/lang/String;[Ljava/lang/Class<*>;Ljava/lang/Class<*>;[Ljava/lang/Class<*>;IILjava/lang/String;[B[B[B)Ljava/lang/reflect/Method; +41 -1: (Ljava/util/jar/JarFile;)Ljava/util/List; +43 -1: (JILjava/lang/Object;)Ljava/nio/ByteBuffer; +19 -1: MethodTypeForm.java +21 -1: java/util/jar/JarFile +30 -1: java/lang/Integer$IntegerCache +22 -1: getDisplayVariantArray +6 -1: setAll +13 -1: ClassValueMap +52 -1: (Ljava/security/PublicKey;Ljava/security/Provider;)V +51 -1: java/util/concurrent/ConcurrentHashMap$BaseIterator +59 -1: (Ljava/lang/Runnable;Ljava/security/AccessControlContext;)V +100 -1: (Ljava/util/concurrent/ConcurrentMap;Ljava/util/function/BiFunction;)Ljava/util/function/BiConsumer; +8 -1: default +13 -1: compareAndSet +10 -1: iso8859-13 +9 -1: putShortB +14 -1: skipDelimiters +28 -1: URI has a fragment component +10 -1: iso8859-15 +42 -1: (Ljava/net/Proxy;)Ljava/net/URLConnection; +23 -1: needsPackageAccessCheck +9 -1: putShortL +3 -1: //[ +69 -1: (Ljava/security/AccessControlContext;Ljava/security/DomainCombiner;)V +18 -1: too many arguments +35 -1: ([III)Ljava/util/Spliterator$OfInt; +10 -1: CopiesList +10 -1: iso-8859-1 +9 -1: ([BII[C)I +10 -1: iso-8859-2 +11 -1: returnCount +10 -1: iso-8859-4 +10 -1: iso-8859-5 +8 -1: utf_16be +10 -1: iso-8859-7 +9 -1: isLimited +9 -1: parseByte +10 -1: iso-8859-9 +13 -1: , s.length() +10 -1: matchCerts +14 -1: RECURSIVE_CHAR +11 -1: reduceToInt +11 -1: displayName +9 -1: calendars +64 -1: (Ljava/lang/String;ZLjava/util/jar/JarEntry;)Lsun/misc/Resource; +11 -1: isProtected +78 -1: (Ljava/util/SortedMap;Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/SortedMap; +4 -1: trim +20 -1: java/nio/FloatBuffer +17 -1: PreHashedMap.java +74 -1: Ljava/util/concurrent/ConcurrentMap; +22 -1: ([S)Ljava/lang/String; +19 -1: PrintStreamOrWriter +38 -1: java/util/Collections$EmptyEnumeration +22 -1: java/util/LinkedList$1 +13 -1: sunpkcs11.jar +25 -1: java/nio/DirectByteBuffer +96 -1: (ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle; +7 -1: isArray +43 -1: (Ljava/lang/String;)Ljava/util/Enumeration; +52 -1: java/lang/invoke/MethodHandleImpl$AsVarargsCollector +59 -1: (Ljava/lang/String;Lsun/misc/Resource;)Ljava/lang/Class<*>; +26 -1: setJavaNetHttpCookieAccess +15 -1: wrongTargetType +57 -1: java/util/concurrent/ConcurrentHashMap$ForEachMappingTask +33 -1: [Ljava/lang/reflect/TypeVariable; +5 -1: load0 +39 -1: (Ljava/lang/String;)Ljava/lang/Boolean; +21 -1: isHeldByCurrentThread +14 -1: outOfBoundsMsg +30 -1: Ljava/lang/ref/Reference$Lock; +11 -1: ISO-8859-13 +84 -1: (Ljava/lang/ClassValue;)Ljava/lang/ClassValue$Entry; +11 -1: ISO-8859-15 +40 -1: (Ljava/net/URL;)Ljava/net/URLConnection; +84 -1: ;>(Ljava/util/Collection<+TT;>;)TT; +38 -1: sun/reflect/generics/scope/MethodScope +5 -1: mutex +11 -1: loaderTypes +8 -1: defaults +22 -1: getActualTypeArguments +41 -1: DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR +4 -1: keys +71 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +94 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/MethodHandle; +113 -1: Ljava/util/AbstractSet;Ljava/util/Set;Ljava/lang/Cloneable;Ljava/io/Serializable; +12 -1: checkConnect +39 -1: (Ljava/lang/String;Ljava/util/Locale;)V +26 -1: ([CII[C)Ljava/lang/String; +12 -1: isDoubleWord +37 -1: configparser JAAS ConfigFile parsing +27 -1: sun/misc/Perf$GetPerfAction +44 -1: (Ljava/util/Collections$UnmodifiableList;I)V +4 -1: acos +26 -1: java/nio/DirectLongBufferS +7 -1: (ITE;)V +14 -1: putIntVolatile +24 -1: setContentHandlerFactory +26 -1: java/nio/DirectLongBufferU +10 -1: fieldCount +11 -1: invokeBasic +50 -1: (Ljava/util/zip/ZipEntry;)Ljava/util/jar/JarEntry; +24 -1: java/util/Locale$Builder +9 -1: setParent +11 -1: asLifoQueue +33 -1: lambda$comparingDouble$8dcf42ea$1 +24 -1: (Ljava/lang/Throwable;)I +35 -1: (Lsun/misc/JavaUtilZipFileAccess;)V +49 -1: (ILjava/lang/Object;)Ljava/util/HashMap$TreeNode; +10 -1: CLASS_PATH +6 -1: tclass +11 -1: getExponent +23 -1: getAnnotatedReturnType0 +18 -1: checkPackageAccess +35 -1: Can not instantiate java.lang.Class +24 -1: (Ljava/lang/Throwable;)V +195 -1: (Ljava/lang/invoke/LambdaForm$Name;Ljava/lang/invoke/LambdaForm$Name;Ljava/lang/invoke/BoundMethodHandle$SpeciesData;Ljava/lang/invoke/BoundMethodHandle$SpeciesData;)Ljava/lang/invoke/LambdaForm; +17 -1: Empty replacement +3 -1: .SF +14 -1: ByteOrder.java +39 -1: ()Lsun/util/calendar/BaseCalendar$Date; +35 -1: ()[Ljava/security/ProtectionDomain; +12 -1: setElementAt +30 -1: (Ljava/security/CodeSource;Z)Z +45 -1: (Ljava/lang/Class<*>;)Ljava/lang/ClassLoader; +52 -1: (Ljava/nio/charset/Charset;)Ljava/util/zip/ZipCoder; +13 -1: foldArguments +23 -1: java/time/LocalDateTime +30 -1: [Lsun/launcher/LauncherHelper; +16 -1: 0123456789abcdef +60 -1: (Ljava/util/Spliterator$OfInt;Z)Ljava/util/stream/IntStream; +33 -1: (ILjava/lang/String;IIIIIIIIIII)V +20 -1: DMH.newInvokeSpecial +28 -1: java/nio/charset/CoderResult +33 -1: sun/nio/cs/StandardCharsets$Cache +11 -1: saveConvert +14 -1: ExtClassLoader +12 -1: parentOrNull +20 -1: insertParameterTypes +32 -1: (II)Ljava/util/stream/IntStream; +13 -1: setStackTrace +20 -1: is not an enum type +3 -1: CNT +4 -1: host +85 -1: ([Ljava/lang/Object;Ljava/util/function/IntFunction;)Ljava/util/function/IntConsumer; +11 -1: batchRemove +8 -1: newField +16 5: sun/nio/cs/UTF_8 +104 -1: (Ljava/lang/invoke/LambdaForm$Name;Ljava/lang/invoke/LambdaForm$Name;)Ljava/lang/invoke/LambdaForm$Name; +8 -1: saturday +35 -1: java/util/ArraysParallelSortHelpers +15 -1: java/util/Queue +40 -1: (Ljava/lang/Class<*>;)Ljava/lang/String; +7 -1: toChars +5 -1: first +17 -1: ArrayDecoder.java +30 -1: ()Lsun/reflect/MethodAccessor; +26 -1: thread group can't be null +13 -1: IllegalName: +32 -1: java/util/Collections$SetFromMap +14 -1: line.separator +17 -1: getDeclaredMethod +10 -1: getMinutes +35 -1: (Lsun/util/locale/BaseLocale$Key;)I +40 -1: ([Ljava/lang/String;)Ljava/lang/Process; +31 -1: Ljava/util/LinkedHashMap$Entry; +13 -1: , str.length +8 -1: getProbe +6 -1: ([DI)I +5 -1: (CI)I +23 -1: saveAndRemoveProperties +6 -1: rehash +3 -1: lcb +31 -1: Ljava/util/Arrays$NaturalOrder; +55 -1: (IILjava/lang/String;)Ljava/lang/AbstractStringBuilder; +10 -1: loadFactor +15 -1: putLongVolatile +34 -1: sun/misc/URLClassPath$FileLoader$1 +12 -1: Europe/Paris +8 -1: DECEMBER +86 -1: Ljava/lang/Object;Ljava/security/PrivilegedAction; +22 -1: getImplMethodSignature +38 -1: Malformed enclosing method information +8 -1: maskNull +3 -1: lct +21 -1: CONSTRUCTOR_MODIFIERS +36 -1: ()Lsun/misc/JavaNetHttpCookieAccess; +12 -1: HashIterator +84 -1: (Ljava/lang/Class;Ljava/lang/Class$AnnotationData;Ljava/lang/Class$AnnotationData;)Z +33 -1: java/lang/Character$UnicodeScript +5 -1: toHex +27 -1: java/security/AllPermission +17 -1: appendReplacement +20 -1: SimpleImmutableEntry +18 -1: getRequestProperty +12 -1: compareCerts +44 -1: java/util/ArrayPrefixHelpers$IntCumulateTask +19 -1: makeSpreadArguments +222 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;Ljava/util/function/Function;Ljava/util/function/BiFunction;)V +8 -1: addFirst +6 -1: nextUp +35 -1: (Ljava/net/ContentHandlerFactory;)V +40 -1: (Ljava/lang/String;)Ljava/lang/Class<*>; +23 -1: java/util/LocaleISOData +14 -1: PREPARED_FORMS +6 -1: FJByte +20 -1: getGenericSuperclass +6 -1: offset +16 -1: LocaleUtils.java +12 -1: isUnresolved +18 -1: aliases_ISO_8859_1 +18 -1: aliases_ISO_8859_2 +15 -1: isSurrogatePair +18 -1: aliases_ISO_8859_4 +18 -1: aliases_ISO_8859_5 +6 -1: EXTLEN +18 -1: aliases_ISO_8859_7 +15 -1: Comparator.java +18 -1: aliases_ISO_8859_9 +15 -1: ISO_8859-2:1987 +22 -1: Ljava/util/List<+TE;>; +16 -1: Unknown Category +3 -1: CST +51 -1: Ljava/util/AbstractList; +6 -1: FRIDAY +40 -1: (Ljava/lang/String;ZZ)Ljava/lang/String; +13 -1: isInterrupted +8 -1: utf_16le +89 -1: (BLjava/lang/Class<*>;Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/DirectMethodHandle; +22 -1: checkInvocationCounter +12 -1: EPOCH_OFFSET +35 -1: (JJILjava/nio/DirectByteBuffer$1;)V +7 -1: canRead +9 -1: getLoader +18 -1: publicConstructors +23 -1: factory already defined +33 -1: java/lang/ref/ReferenceQueue$Null +37 -1: (Ljava/util/List;Ljava/util/Random;)V +25 -1: setPackageAssertionStatus +20 -1: MapReduceEntriesTask +11 -1: OPEN_DELETE +35 -1: (Ljava/util/Set;Ljava/lang/Class;)V +9 -1: rootGroup +10 -1: updateForm +22 -1: JavaUtilJarAccess.java +3 -1: CTT +57 -1: (Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Constructor; +82 -1: (Ljava/util/NavigableSet;)Ljava/util/NavigableSet; +13 -1: getReturnType +34 -1: java/util/HashMap$EntrySpliterator +14 -1: TIME_UNDEFINED +32 -1: com/sun/crypto/provider/AESCrypt +7 -1: H_DIGIT +20 -1: clearAssertionStatus +44 -1: java/lang/invoke/MethodHandleImpl$BindCaller +8 -1: scloader +6 -1: IBM923 +5 -1: read0 +5 -1: read1 +4 -1: true +9 -1: BA_HIDDEN +16 -1: jvmUpdateVersion +36 -1: java/lang/StringCoding$StringDecoder +37 -1: (J)Ljava/nio/file/attribute/FileTime; +3 -1: lib +17 -1: getParameterTypes +15 -1: FinalizerThread +31 -1: ()Lsun/util/calendar/Gregorian; +50 -1: (Ljava/lang/CharSequence;)Ljava/lang/StringBuffer; +13 -1: PROP_SETTINGS +33 -1: java/util/function/BinaryOperator +70 -1: (ILjava/util/List;>;)Ljava/lang/invoke/MethodType; +25 -1: getDefaultRequestProperty +27 -1: (Ljava/util/jar/JarEntry;)V +27 -1: SPLITERATOR_CHARACTERISTICS +18 -1: FieldAccessor.java +10 -1: setComment +62 -1: (Ljava/lang/String;)Ljava/lang/management/MemoryManagerMXBean; +11 -1: array_klass +39 -1: ()Ljava/lang/Class$EnclosingMethodInfo; +67 -1: ([Ljava/lang/ClassValue$Entry<*>;ILjava/lang/ClassValue$Entry<*>;)I +9 -1: (II[CII)I +50 -1: (Ljava/util/jar/JarFile;Ljava/util/zip/ZipEntry;)V +20 -1: SPECIFICATION_VENDOR +72 -1: (Lsun/misc/URLClassPath$JarLoader;Ljava/net/URL;)Ljava/util/jar/JarFile; +87 -1: (Ljava/lang/ThreadLocal;>;TT;)V +9 -1: isVarArgs +10 -1: setBoolean +12 -1: (TK;TV;TV;)Z +16 -1: findSharedClass0 +5 -1: csize +49 -1: Ljava/security/cert/CertificateEncodingException; +40 -1: java/util/concurrent/locks/ReentrantLock +86 -1: (Ljava/io/OutputStream;Ljava/lang/Object;Ljava/lang/String;)Lsun/nio/cs/StreamEncoder; +5 -1: ready +38 -1: Ljava/security/AccessControlException; +28 -1: UnmodifiableRandomAccessList +69 -1: ([TT;Ljava/util/function/BinaryOperator;)V +27 -1: Ljava/lang/invoke/Invokers; +39 -1: java/util/LinkedList$DescendingIterator +11 -1: writeFields +17 -1: classLoaderDepth0 +18 -1: permutedTypesMatch +52 -1: (Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/List; +12 -1: linkToStatic +10 -1: CheckedMap +6 -1: CENOFF +8 -1: lastRule +15 -1: java/lang/Short +39 -1: ()Ljava/lang/Class$ReflectionData; +8 -1: nextDown +14 -1: image/x-pixmap +39 -1: (Ljava/lang/Class;[Ljava/lang/Object;)V +25 -1: defineClassSourceLocation +23 -1: sun/misc/PostVMInitHook +15 -1: could not load +16 -1: allowArraySyntax +90 -1: Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater; +10 -1: putBoolean +11 -1: has params +14 -1: setMaxPriority +10 -1: mayContain +46 -1: java/lang/reflect/MalformedParametersException +10 -1: baseLocale +14 -1: isSubwordOrInt +10 -1: nextDouble +32 -1: java/lang/Character$UnicodeBlock +85 -1: (JLjava/util/function/ToDoubleBiFunction;DLjava/util/function/DoubleBinaryOperator;)D +20 -1: numberOfLeadingZeros +59 -1: (I[Ljava/lang/Class<*>;)[Ljava/lang/invoke/LambdaForm$Name; +7 -1: setSize +29 -1: java/io/FileNotFoundException +9 -1: getString +24 -1: ([CII)Ljava/lang/String; +38 -1: (Ljava/lang/String;Ljava/lang/Class;)V +5 -1: shift +18 -1: getConstructorSlot +41 -1: java/lang/ThreadLocal$SuppliedThreadLocal +16 -1: UNASSIGNED_STACK +20 -1: Malformed class name +12 -1: ofEpochMilli +34 -1: sun/launcher/LauncherHelper$StdArg +33 -1: java/nio/ByteBufferAsShortBufferB +7 -1: convert +21 -1: ()[Ljava/util/Locale; +15 -1: ISO_8859-5:1988 +35 -1: av[0] not instace of MethodHandle: +33 -1: java/nio/ByteBufferAsShortBufferL +5 -1: hypot +16 -1: InputStream.java +13 -1: reinvokerForm +39 -1: JVMTI_THREAD_STATE_WAITING_INDEFINITELY +16 -1: sun/misc/Version +66 -1: (Ljava/lang/Class;)[TT; +11 -1: codePointAt +30 -1: ([Ljava/lang/reflect/Method;)V +9 -1: duplicate +9 -1: interface +5 -1: X.509 +24 -1: SynchronizedNavigableSet +8 -1: us-ascii +17 -1: getUnresolvedType +21 -1: PRIVATE_USE_EXTENSION +4 -1: form +93 -1: (Ljava/util/ArrayPrefixHelpers$LongCumulateTask;Ljava/util/function/LongBinaryOperator;[JII)V +27 -1: sealing violation: package +34 -1: RuntimeVisibleParameterAnnotations +17 -1: LF_INVSTATIC_INIT +14 -1: Gregorian.java +32 -1: java/util/function/UnaryOperator +3 -1: log +3 -1: low +22 -1: sun/misc/JavaNetAccess +9 -1: getLength +21 -1: getRawTypeAnnotations +36 -1: (Ljava/lang/String;)Ljava/lang/Long; +9 -1: getNumber +66 -1: (ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node; +20 -1: (Ljava/lang/Class;)C +89 -1: Ljava/lang/Object;Ljava/util/Map$Entry; +6 -1: ENDSIG +20 -1: (Ljava/lang/Class;)I +20 -1: (Ljava/lang/Class;)J +24 -1: [[Ljava/io/Serializable; +22 -1: serialPersistentFields +7 -1: console +142 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +27 -1: (Ljava/nio/ByteBuffer;ICZ)V +20 -1: (Ljava/lang/Class;)V +40 -1: java/lang/ArrayIndexOutOfBoundsException +6 -1: this$0 +51 -1: (Ljava/lang/invoke/MemberName;[Ljava/lang/Object;)V +18 -1: packageAccessValid +33 -1: ([Ljava/lang/StackTraceElement;)V +8 -1: constant +113 -1: (Ljava/lang/String;Ljava/nio/ByteBuffer;IILjava/security/ProtectionDomain;Ljava/lang/String;)Ljava/lang/Class<*>; +8 -1: isMethod +20 -1: (Ljava/lang/Class;)Z +6 -1: ENDSIZ +8 -1: newEntry +57 -1: (Ljava/lang/Object;)Ljava/lang/IndexOutOfBoundsException; +25 -1: (Ljava/util/Comparator;)V +8 -1: isBridge +6 -1: ([BI)I +6 -1: ([BI)J +16 -1: getReferenceKind +26 -1: [Ljava/security/Principal; +71 -1: (Ljava/lang/Class;[Ljava/lang/reflect/Field;)[Ljava/lang/reflect/Field; +32 -1: ()Ljava/lang/ClassValue$Version; +16 -1: SearchValuesTask +17 -1: setCompressedSize +16 -1: DEFAULT_CAPACITY +108 -1: ;>()Ljava/util/Comparator;>; +27 -1: java/util/ComparableTimSort +41 -1: null StackTraceElement in serial stream. +6 -1: ([BI)V +44 -1: (Ljava/util/jar/JarFile;)Lsun/misc/JarIndex; +71 -1: (Ljava/util/jar/JarFile;Ljava/util/Enumeration;)Ljava/util/Enumeration; +52 -1: (Ljava/lang/invoke/MemberName;Ljava/lang/Class<*>;)Z +36 -1: [Ljava/lang/reflect/TypeVariable<*>; +17 -1: OutputStream.java +8 -1: combiner +15 -1: decodeArrayLoop +19 -1: (Ljava/io/Writer;)V +41 -1: (Ljava/util/List<*>;Ljava/util/List<*>;)I +35 -1: ()[Ljava/security/cert/Certificate; +33 -1: ([I)Ljava/util/Spliterator$OfInt; +9 -1: NF_asType +17 -1: java/io/Closeable +11 -1: updateBytes +12 -1: charsets.jar +18 -1: getDeclaredFields0 +47 -1: (Ljava/lang/Object;I)Ljava/lang/reflect/Member; +60 -1: (Ljava/lang/String;ILjava/lang/String;)Ljava/nio/ByteBuffer; +15 -1: getTotalSeconds +57 -1: (Ljava/util/Collection<+Ljava/util/Map$Entry;>;)Z +4 -1: JULY +10 -1: Exceptions +41 -1: ()Ljava/util/List; +14 -1: ParseUtil.java +13 -1: getJarFileURL +29 -1: setJavaIOFileDescriptorAccess +24 -1: ARRAY_OBJECT_BASE_OFFSET +21 -1: onUnmappableCharacter +53 -1: (Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Map; +24 -1: MethodHandleNatives.java +40 -1: java/nio/charset/MalformedInputException +37 -1: [Ljava/lang/reflect/AnnotatedElement; +15 -1: CLASSPATH_CHARS +18 -1: [Ljava/lang/Class; +7 -1: FJFloat +47 -1: (Ljava/util/List;I)V +19 -1: Ljava/lang/Runtime; +23 -1: java/lang/CharacterData +42 -1: (Ljava/lang/Void;Ljava/lang/ClassLoader;)V +76 -1: (Ljava/nio/channels/ReadableByteChannel;Ljava/nio/charset/CharsetDecoder;I)V +56 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;B)V +19 -1: java/util/zip/CRC32 +33 -1: ([TT;I)[TT; +22 -1: ([F)Ljava/lang/String; +5 -1: UTF_8 +20 -1: aliases_UTF_32BE_BOM +11 -1: Buffer.java +78 -1: (Ljava/util/Comparator;)Ljava/util/Comparator; +44 -1: (Ljava/lang/String;)Ljava/util/zip/ZipEntry; +9 -1: malformed +4 -1: JUNE +51 -1: (Ljava/util/jar/JarFile;Ljava/util/jar/JarFile$1;)V +6 -1: locale +34 -1: (Ljava/util/function/BiFunction;)V +10 -1: setMinutes +40 -1: (Ljava/lang/reflect/AccessibleObject;Z)V +12 -1: maybeCompile +46 -1: (Ljava/lang/Class;Ljava/lang/reflect/Method;)V +7 -1: getEras +55 -1: ([TT;Ljava/util/Iterator<*>;)[TT; +17 -1: toUnsignedString0 +32 -1: (Ljava/lang/invoke/MethodType;)V +32 -1: (Ljava/lang/invoke/MethodType;)Z +10 -1: Class.java +27 -1: ()Ljava/util/Iterator; +29 -1: WINDOWS_EPOCH_IN_MICROSECONDS +41 -1: (Ljava/io/InputStream;)Ljava/lang/String; +4 -1: prev +24 -1: ()Ljava/util/Properties; +11 -1: awaitBooted +19 -1: generateConstructor +22 -1: sun/misc/SharedSecrets +19 -1: getDateTimeInstance +43 -1: (IIILsun/util/calendar/BaseCalendar$Date;)J +5 -1: setID +11 -1: Locale.java +12 -1: getRootGroup +15 -1: setLastModified +7 -1: trouble +28 -1: (Z)Ljava/lang/StringBuilder; +5 -1: setIO +17 -1: loadClassInternal +23 -1: java/lang/ref/Finalizer +8 -1: EmptySet +16 -1: aliases_UTF_16BE +50 -1: (Ljava/util/NavigableMap;)Ljava/util/NavigableMap; +15 -1: unmodifiableMap +48 -1: (Ljava/lang/Class<*>;)Lsun/reflect/ConstantPool; +15 -1: arrayContentsEq +7 -1: EXT_TAG +31 -1: (Ljava/util/HashMap$TreeNode;)Z +5 -1: cp737 +22 -1: java/util/zip/Checksum +5 -1: names +22 -1: ConcurrentHashMap.java +7 -1: ([J[J)Z +7 -1: WAITING +31 -1: sun.launcher.resources.launcher +14 -1: getThreadGroup +8 -1: PutField +12 -1: hugeCapacity +9 -1: isPackage +72 -1: (Ljava/lang/ThreadLocal<*>;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry; +23 7: sun/nio/ch/DirectBuffer +13 -1: Checksum.java +25 -1: (Ljava/nio/ByteBuffer;I)C +51 -1: (Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object; +25 -1: (Ljava/nio/ByteBuffer;I)D +7 -1: treeify +25 -1: (Ljava/nio/ByteBuffer;I)F +5 -1: setIn +25 -1: (Ljava/nio/ByteBuffer;I)I +20 -1: TRACE_METHOD_LINKAGE +25 -1: (Ljava/nio/ByteBuffer;I)J +7 -1: putIntB +22 -1: createGarbageCollector +50 -1: (Ljava/lang/Class;)[TT; +25 -1: (Ljava/nio/ByteBuffer;I)S +7 -1: putIntL +19 -1: (B)Ljava/lang/Byte; +14 -1: Hashtable.java +29 -1: java/lang/ArrayStoreException +11 -1: all_allowed +16 -1: getLastRawOffset +7 -1: inReady +36 -1: java/lang/ThreadLocal$ThreadLocalMap +40 -1: (ILjava/lang/String;Ljava/lang/String;)V +23 -1: Ljava/lang/ThreadLocal; +16 -1: classValueOrNull +62 -1: (Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/MethodHandle; +23 -1: preparedFieldLambdaForm +22 -1: (Z)Ljava/lang/Boolean; +14 -1: ThreadLocalMap +27 -1: java/lang/StackTraceElement +13 -1: getEntryCSize +19 -1: java.security.debug +53 -1: (Ljava/util/Collection<*>;Ljava/util/Collection<*>;)Z +6 -1: LOCLEN +40 -1: Ljava/lang/Class; +6 -1: (JJB)V +66 -1: Ljava/util/Hashtable; +31 -1: [[Ljava/lang/StackTraceElement; +9 -1: putStatic +16 -1: Asia/Ho_Chi_Minh +15 -1: getDisplayNames +13 -1: convertToAbbr +23 -1: Method not implemented. +15 -1: isCCLOverridden +14 -1: doubleCapacity +137 -1: (Ljava/lang/Class<*>;ZLjava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class<*>;)Ljava/util/List; +219 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;Ljava/util/function/Function;Ljava/util/function/BiFunction;)V +7 -1: native +29 -1: (Ljava/lang/reflect/Field;Z)V +18 -1: Ljava/util/Locale; +31 -1: Ljava/util/concurrent/TimeUnit; +16 -1: threadsSuspended +7 -1: ([III)V +20 -1: setMaxDelimCodePoint +18 -1: contentClassPrefix +13 -1: mappingOffset +10 -1: toIndex = +47 -1: (Ljava/lang/CharSequence;)Ljava/io/PrintStream; +12 -1: booleanValue +13 -1: putMapEntries +17 -1: defaultBundleName +50 -1: (Ljava/util/concurrent/CountedCompleter;[B[BIIII)V +10 -1: executable +20 -1: java/time/ZoneOffset +28 -1: java/lang/ref/FinalReference +11 -1: newTreeNode +7 -1: lookup2 +10 -1: TableStack +59 -1: Ljava/util/concurrent/ConcurrentHashMap$ValuesView; +11 -1: getAccessor +9 -1: available +18 -1: java/io/FileReader +34 -1: java/security/ProtectionDomain$3$1 +16 -1: integer overflow +11 -1: internTable +28 -1: Ljava/util/HashMap$TreeNode; +19 -1: | invocationCounter +12 -1: findResource +9 -1: isLoaded0 +5 -1: cp775 +24 -1: DIRECTIONALITY_UNDEFINED +9 -1: isInvalid +7 -1: lookupN +35 -1: (Lsun/reflect/MethodAccessorImpl;)V +6 -1: ENDSUB +4 -1: to +59 -1: ([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object; +10 -1: meta-index +6 -1: INDENT +9 -1: WEDNESDAY +40 -1: ()Ljava/lang/annotation/RetentionPolicy; +14 -1: getUsableSpace +7 -1: TUESDAY +51 -1: (Ljava/lang/Class;I)Ljava/lang/invoke/MethodHandle; +12 -1: getSubjectDN +21 -1: Ljava/io/InputStream; +25 -1: (IC)Ljava/nio/CharBuffer; +52 -1: (Ljava/nio/CharBuffer;)Ljava/util/function/Supplier; +17 -1: ()[Ljava/net/URL; +6 -1: search +10 -1: Main-Class +8 -1: ([CIIC)I +16 -1: Certificate.java +14 -1: spreadInvokers +22 -1: sun/nio/cs/ISO_8859_15 +6 -1: accept +18 -1: ReflectAccess.java +13 -1: java/nio/Bits +14 -1: linkToCallSite +46 -1: Ljava/nio/charset/UnsupportedCharsetException; +8 -1: ([CIIC)V +9 -1: (TT;TV;)V +26 -1: java/lang/OutOfMemoryError +34 -1: policy loading and granting +76 -1: (Ljava/nio/CharBuffer;ILjava/nio/ByteBuffer;I)Ljava/nio/charset/CoderResult; +13 -1: x-windows-949 +21 -1: Ljava/io/PrintStream; +9 -1: initNames +12 -1: testAnyFlags +65 -1: (Ljava/lang/reflect/Method;)Ljava/lang/invoke/DirectMethodHandle; +34 -1: (Ljava/util/List;)Ljava/util/List; +10 -1: CacheEntry +10 -1: hasAllPerm +26 -1: java/nio/charset/Charset$1 +26 -1: java/nio/charset/Charset$2 +19 -1: ()Ljava/util/Stack; +26 -1: java/nio/charset/Charset$3 +62 -1: (Ljava/lang/String;)Lsun/util/calendar/LocalGregorianCalendar; +23 -1: ARRAY_FLOAT_INDEX_SCALE +23 -1: (Ljava/lang/Object;IS)V +13 -1: x-windows-950 +31 -1: Ljava/util/Hashtable$Entry<**>; +87 -1: Ljava/util/WeakHashMap;>; +9 -1: permClass +37 -1: (Ljava/security/ProtectionDomain$3;)V +99 -1: Lsun/reflect/generics/repository/AbstractRepository; +37 -1: ()Ljava/util/function/BinaryOperator; +64 -1: java/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap +91 -1: (Ljava/util/ArrayPrefixHelpers$IntCumulateTask;Ljava/util/function/IntBinaryOperator;[III)V +6 -1: getCrc +25 -1: ByteArrayInputStream.java +9 -1: SYNTHETIC +52 -1: Ljava/lang/ref/PhantomReference; +246 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;Ljava/util/function/ToDoubleFunction;DLjava/util/function/DoubleBinaryOperator;)V +38 -1: java/lang/Throwable$WrappedPrintStream +21 -1: Illegal load factor: +43 -1: Ljava/util/Deque; +3 -1: map +6 -1: expand +6 -1: access +3 -1: max +33 -1: impliesCreateAccessControlContext +3 -1: may +53 -1: java/util/concurrent/ConcurrentHashMap$ReduceKeysTask +91 -1: Ljava/lang/Object;Ljava/security/PrivilegedExceptionAction; +60 -1: attempt to add a Permission to a readonly Permissions object +21 -1: canonicalizeExtension +11 -1: copyValueOf +25 -1: (IJ)Ljava/nio/LongBuffer; +112 -1: (JLjava/util/function/Function<-TV;+TU;>;Ljava/util/function/BiFunction<-TU;-TU;+TU;>;)TU; +11 -1: DeqIterator +11 -1: SpeciesData +8 -1: getCause +16 -1: aliases_UTF_16LE +51 -1: (TT;TV;Ljava/util/function/BinaryOperator;)TV; +25 -1: (JF)Ljava/nio/ByteBuffer; +16 -1: sun/misc/IOUtils +32 -1: Ljava/util/Locale$FilteringMode; +6 -1: .class +13 -1: getPermission +13 -1: startsWithLOC +8 -1: Identity +23 -1: ([BII)Ljava/lang/Class; +15 -1: putByteVolatile +36 -1: (Ljava/util/Deque;)Ljava/util/Queue; +22 -1: (Ljava/lang/Object;S)V +47 -1: java/util/concurrent/ConcurrentHashMap$BulkTask +4 -1: n = +9 -1: (ITE;)TE; +5 -1: zeroD +18 -1: formatUnsignedLong +29 -1: default display locale = +23 -1: java/io/File$PathStatus +5 -1: zeroF +20 -1: Ljava/util/Set; +20 -1: (Ljava/util/List;I)V +5 -1: zeroI +5 -1: zeroJ +7 -1: context +39 -1: Ljava/nio/channels/WritableByteChannel; +5 -1: zeroL +34 -1: Lsun/util/calendar/CalendarSystem; +24 -1: JVMTI_THREAD_STATE_ALIVE +18 -1: (Ljava/util/Set;)V +18 -1: (Ljava/util/Set;)Z +42 -1: (TT;Ljava/lang/ref/ReferenceQueue<-TT;>;)V +7 -1: entries +30 -1: (Ljava/util/WeakHashMap;IIII)V +15 -1: csisolatingreek +38 -1: ([Ljava/lang/Class;)Ljava/lang/Object; +12 -1: isMalformed3 +12 -1: isMalformed4 +5 -1: FJInt +23 -1: java/util/LinkedHashMap +20 -1: malformedInputAction +12 -1: Charset.java +5 -1: LLL_L +42 -1: (Ljava/util/Collection;)Ljava/lang/Object; +22 -1: makeMethodHandleInvoke +3 -1: mdt +7 -1: unicode +12 -1: newInstance0 +10 -1: checkCerts +34 -1: java/util/WeakHashMap$HashIterator +23 -1: (Ljava/lang/Object;JI)I +9 -1: hexDigits +13 -1: javaToDosTime +24 -1: (I)Ljava/nio/LongBuffer; +6 -1: A_DATA +12 -1: deepToString +23 -1: (Ljava/lang/Object;JI)V +91 -1: (JLjava/util/function/ToLongBiFunction<-TK;-TV;>;JLjava/util/function/LongBinaryOperator;)J +23 -1: bad spread array length +11 -1: readTimeout +14 -1: toAbsolutePath +8 -1: isFinite +19 -1: currentLoadedClass0 +3 -1: \xef\xbf\xbd +23 -1: (Ljava/nio/file/Path;)I +8 -1: handlers +21 -1: (Ljava/util/List;II)V +89 -1: (Lsun/misc/URLClassPath$Loader;Ljava/lang/String;Ljava/net/URL;Ljava/net/URLConnection;)V +8 -1: OVERFLOW +8 -1: newTable +8 -1: THURSDAY +6 -1: notify +12 -1: initialValue +35 -1: (I)Ljava/util/LinkedList$Node; +18 -1: AsVarargsCollector +26 -1: (Lsun/misc/JavaIOAccess;)V +18 -1: ()Ljava/lang/Void; +23 -1: (Ljava/nio/file/Path;)Z +16 -1: MINUTE_IN_MILLIS +67 -1: (Ljava/lang/Class;[Ljava/lang/Class;Z)Ljava/lang/invoke/MethodType; +18 -1: Ljava/util/Vector; +70 -1: (Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)Ljava/lang/Object; +40 -1: (Ljava/lang/Object;ILjava/lang/Object;)V +25 -1: UnresolvedPermission.java +14 -1: ReduceKeysTask +21 -1: ()[Ljava/lang/Object; +129 -1: Ljava/lang/Object;Ljava/util/Collection;Ljava/io/Serializable; +16 -1: ClassLoader.java +46 -1: Ljava/util/Comparators$NaturalOrderComparator; +17 -1: compareAndSwapInt +22 -1: packageDefinitionValid +41 -1: ([Ljava/lang/Object;[Ljava/lang/Object;)Z +162 -1: (Ljava/util/List;Ljava/util/Collection;Ljava/util/Locale$FilteringMode;)Ljava/util/List; +16 -1: sun.zip.zipFiles +17 -1: java_runtime_name +31 -1: (Ljava/lang/ClassValue$Entry;)V +31 -1: (Ljava/lang/ClassValue$Entry;)Z +30 -1: (TT;)TT; +39 -1: JavaSecurityProtectionDomainAccess.java +24 -1: (I)Ljava/lang/Throwable; +7 -1: FJShort +9 -1: putFloatB +19 -1: checkedNavigableSet +25 -1: java/lang/invoke/Invokers +18 -1: setIfModifiedSince +14 -1: parameterTypes +41 -1: (Ljava/lang/Object;Ljava/lang/Runnable;)V +9 -1: putFloatL +11 -1: getTypeCode +5 -1: (ZZ)I +24 -1: java/lang/ProcessBuilder +9 -1: UNDERFLOW +21 -1: VolatileCallSite.java +24 -1: (C)Ljava/nio/CharBuffer; +55 -1: java/util/concurrent/ConcurrentHashMap$ForEachValueTask +26 -1: (Ljava/lang/String;[CII)[B +18 -1: reduceKeysToDouble +5 -1: (ZZ)Z +23 -1: setCallSiteTargetNormal +3 -1: min +4 -1: ceil +62 -1: (Ljava/lang/String;)Ljava/util/LinkedList; +29 -1: (Ljava/util/AbstractList;II)V +32 -1: Ljava/lang/Class$AnnotationData; +21 -1: createFileExclusively +64 -1: (Ljava/lang/ref/SoftReference;I)Ljava/lang/Class$ReflectionData; +26 -1: java/lang/Short$ShortCache +54 -1: (Ljava/net/URL;Ljava/io/File;)Ljava/net/URLConnection; +29 -1: Lsun/nio/cs/Surrogate$Parser; +58 -1: (Ljava/lang/Class;)Lsun/reflect/annotation/AnnotationType; +8 -1: findForm +53 -1: Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet; +39 -1: (Lsun/misc/Perf;Ljava/nio/ByteBuffer;)V +16 -1: mergePermissions +11 -1: totalMemory +53 -1: java/lang/invoke/DirectMethodHandle$EnsureInitialized +139 -1: Ljava/util/AbstractMap;Ljava/util/concurrent/ConcurrentMap;Ljava/io/Serializable; +29 -1: java/util/HashMap$KeyIterator +20 -1: STACK_TRACE_SENTINEL +5 -1: order +18 -1: java/lang/Runnable +8 -1: GetField +13 -1: Empty command +7 -1: CONTROL +9 -1: blockedOn +12 -1: testAllFlags +11 -1: getInflater +16 -1: threadTerminated +44 -1: (Ljava/lang/ThreadGroup;Ljava/lang/String;)V +20 -1: java.runtime.version +8 -1: peekLast +23 -1: java/util/ArrayList$Itr +21 -1: (Ljava/util/Locale;)V +13 -1: isOptimizable +8 -1: FairSync +7 -1: CHINESE +15 -1: initHelpMessage +30 -1: ()Ljava/util/HashMap$TreeNode; +29 -1: Ljava/lang/SecurityException; +7 -1: charset +35 -1: sun/security/util/SecurityConstants +19 -1: sun.nio.cs.bugLevel +8 2: Foo.java +49 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;)V +12 -1: EntrySetView +37 -1: (Lsun/misc/JavaNetHttpCookieAccess;)V +35 -1: Ljava/util/Hashtable$Entry; +20 -1: NF_constructorMethod +8 -1: getMonth +38 -1: (Ljava/util/Iterator;Ljava/util/Map;)V +14 -1: getIntVolatile +6 -1: [name= +8 -1: oop_size +20 -1: Can't load library: +30 -1: ()Ljava/util/Spliterator; +33 -1: Lsun/reflect/ConstructorAccessor; +61 -1: Ljava/lang/Number;Ljava/lang/Comparable; +15 -1: printVmSettings +33 -1: stack include stack trace +45 -1: ([Ljava/lang/Object;I)Ljava/util/Spliterator; +37 -1: sun/reflect/generics/scope/ClassScope +36 -1: java/io/UnsupportedEncodingException +24 -1: (J)Ljava/nio/LongBuffer; +11 -1: addressSize +15 -1: ByteBuffer.java +62 -1: (Ljava/lang/String;)Lsun/reflect/generics/tree/ClassSignature; +9 -1: (TT;TT;)I +25 -1: java/io/DefaultFileSystem +15 -1: BaseLocale.java +14 -1: BitSetIterator +17 -1: AbstractList.java +57 -1: Ljava/lang/ref/WeakReference;>; +178 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +9 -1: arguments +26 -1: java/util/Locale$LocaleKey +9 -1: setLength +29 -1: sun/nio/cs/ISO_8859_1$Decoder +9 -1: zipfs.jar +24 -1: Ljava/util/zip/ZipCoder; +14 -1: , new state = +93 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;IIIJLjava/util/concurrent/ConcurrentHashMap;)V +39 -1: java/security/PrivilegedExceptionAction +9 -1: dnsns.jar +20 -1: iteratorBinarySearch +14 -1: initializePath +22 -1: DefaultFileSystem.java +17 -1: Ljava/util/Deque; +8 -1: DEFLATED +11 -1: Can't load +9 -1: ArrayList +21 -1: negativeZeroFloatBits +41 -1: (Ljava/lang/String;ILjava/util/Locale;)[C +14 -1: ANSI_X3.4-1968 +39 -1: sun/reflect/annotation/AnnotationType$1 +3 -1: mod +62 -1: Ljava/nio/Buffer;Ljava/lang/Comparable; +29 -1: interpretWithArgumentsTracing +6 -1: getDay +47 -1: sun/reflect/generics/repository/ClassRepository +19 -1: refKindDoesDispatch +20 -1: getAnnotationsByType +14 -1: needsExpansion +18 -1: lastIndexOfSubList +26 -1: JavaUtilZipFileAccess.java +59 -1: (Ljava/lang/CharSequence;)Ljava/lang/AbstractStringBuilder; +12 -1: ptypesOffset +8 -1: hashcode +18 -1: ([Ljava/net/URL;)V +8 -1: iso-ir-6 +7 -1: jzentry +52 -1: only dump output if specified codebase +31 -1: lambda$comparingLong$6043328a$1 +5 -1: MARCH +14 -1: ANSI_X3.4-1986 +14 -1: isMalformed3_2 +7 -1: IS_TYPE +68 -1: Ljava/lang/Object;Ljava/lang/Comparable; +30 -1: protocol doesn't support input +17 -1: getExtClassLoader +14 -1: setProxiedHost +73 -1: ()Ljava/util/Map;>; +16 -1: traceInterpreter +17 -1: (Ljava/net/URL;)I +5 -1: expm1 +18 -1: createInheritedMap +66 -1: java/util/concurrent/ConcurrentHashMap$ForEachTransformedEntryTask +17 -1: getTimeOfDayValue +15 -1: zeroLengthArray +20 -1: invalid permission: +6 -1: REPORT +15 -1: isNumericString +78 -1: (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter; +6 -1: (TV;)Z +25 -1: Lsun/misc/JavaLangAccess; +29 -1: (I)Ljava/lang/reflect/Method; +17 -1: (Ljava/net/URL;)V +34 -1: ()Ljava/lang/Class$ReflectionData; +50 -1: java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE +10 -1: copyWith: +17 -1: (Ljava/net/URL;)Z +32 -1: ()Ljava/util/stream/Stream; +22 -1: quickCheckMemberAccess +29 -1: ()Lsun/net/www/MessageHeader; +19 -1: getAssignedCombiner +8 -1: ([JIIJ)I +17 -1: formatUnsignedInt +68 -1: Ljava/util/AbstractMap; +34 -1: java/nio/ByteBufferAsDoubleBufferB +32 -1: ([I)Ljava/util/stream/IntStream; +9 -1: init_lock +18 -1: must be resolved: +42 -1: ()Ljava/nio/channels/spi/SelectorProvider; +8 -1: ([JIIJ)V +33 -1: IncompatibleClassChangeError.java +34 -1: java/nio/ByteBufferAsDoubleBufferL +31 -1: ()Ljava/util/function/Function; +43 -1: Ljava/lang/Enum; +17 -1: availableCharsets +49 -1: java/util/ArraysParallelSortHelpers$FJChar$Sorter +22 -1: permission= +22 -1: getAnnotatedSuperclass +20 -1: isObjectPublicMethod +15 -1: Attempt to get +10 -1: createLong +14 -1: HASH_INCREMENT +32 -1: sun/management/ManagementFactory +13 -1: separatorChar +15 -1: bad field type +8 -1: november +27 -1: (F)Ljava/lang/StringBuffer; +3 -1: EAT +3 -1: mst +54 -1: (Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method; +18 -1: Ljava/lang/Object; +7 -1: ;:&=+$, +12 -1: Handler.java +7 -1: isDirty +127 -1: (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;[Ljava/security/Permission;)TT; +14 -1: asTypeUncached +5 -1: split +200 -1: ([BLsun/reflect/ConstantPool;Ljava/lang/reflect/AnnotatedElement;Ljava/lang/Class;Ljava/lang/reflect/Type;Lsun/reflect/annotation/TypeAnnotation$TypeAnnotationTarget;)Ljava/lang/reflect/AnnotatedType; +47 -1: java.lang.invoke.MethodHandle.TRACE_INTERPRETER +22 -1: sun/invoke/empty/Empty +66 -1: (Ljava/util/Map;Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/Map; +18 -1: jvm_update_version +32 -1: (Ljava/util/Map;)Ljava/util/Map; +14 -1: cacheLoadLimit +8 -1: javaHome +52 -1: (Ljava/lang/reflect/Field;)Ljava/lang/reflect/Field; +20 -1: [[Ljava/lang/Object; +19 -1: isJavaLetterOrDigit +11 -1: loadLibrary +32 -1: java/io/StreamCorruptedException +14 -1: setAccessible0 +27 -1: sun/nio/cs/UTF_16LE$Encoder +60 -1: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; +8 -1: segments +10 -1: UTF_8.java +3 -1: ECT +5 -1: cp813 +5 -1: cp819 +61 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/util/Comparator;)I +5 -1: Cache +4 -1: sinh +32 -1: java/util/function/ToIntFunction +10 -1: setFactory +24 -1: Illegal mappings count: +16 -1: fileToEncodedURL +38 -1: Ljava/lang/annotation/RetentionPolicy; +27 -1: Ljava/net/SocketPermission; +46 -1: (Ljava/lang/CharSequence;I)[Ljava/lang/String; +11 -1: cardinality +13 -1: getMonthValue +64 -1: (Ljava/lang/invoke/MethodType;II)Ljava/lang/invoke/MethodHandle; +6 -1: ENDTOT +12 -1: getBytesUTF8 +9 -1: cacheLoad +13 -1: packageAccess +14 -1: sharedToString +5 -1: merge +29 -1: parameter type cannot be void +27 -1: makePreparedFieldLambdaForm +40 -1: Couldn't find 3-letter country code for +166 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/net/URL;Ljava/lang/ClassLoader;)V +19 -1: (Ljava/util/Map;Z)V +13 -1: setExecutable +17 -1: objectFieldOffset +57 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V +128 -1: (Ljava/lang/Class<*>;ZLjava/lang/String;Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Ljava/util/List; +61 -1: java/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask +6 -1: asType +25 -1: java/io/ObjectStreamField +15 -1: jvmMajorVersion +124 -1: (Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;[Ljava/security/Permission;)Ljava/lang/Object; +23 -1: (Ljava/lang/Class<*>;)C +6 -1: andNot +15 -1: getResponseCode +59 -1: (Ljava/lang/StringBuffer;)Ljava/lang/AbstractStringBuilder; +23 -1: (Ljava/lang/Class<*>;)I +7 -1: seeAllp +44 -1: (Ljava/lang/ClassLoader;[Ljava/lang/Class;)V +13 -1: loadFromCache +35 -1: sun/nio/cs/HistoricallyNamedCharset +38 -1: (Ljava/lang/Class;[Ljava/lang/Class;)V +19 -1: INVOKER_METHOD_TYPE +16 -1: putShortVolatile +12 -1: Asia/Karachi +8 -1: cyrillic +12 -1: getISO2Table +23 -1: (Ljava/lang/Class<*>;)V +3 -1: 1.4 +15 -1: LongBuffer.java +6 -1: (IFZ)V +23 -1: (Ljava/lang/Class<*>;)Z +10 -1: initOutput +9 -1: CELLSBUSY +39 -1: java/security/PrivilegedActionException +31 -1: sun/util/calendar/CalendarUtils +202 -1: ([BLsun/reflect/ConstantPool;Ljava/lang/reflect/AnnotatedElement;Ljava/lang/Class;[Ljava/lang/reflect/Type;Lsun/reflect/annotation/TypeAnnotation$TypeAnnotationTarget;)[Ljava/lang/reflect/AnnotatedType; +20 -1: Ljava/lang/Class<*>; +5 -1: cp850 +25 -1: (JI)Ljava/nio/ByteBuffer; +5 -1: cp852 +24 -1: Invalid parameter name " +39 -1: ([CII)Ljava/lang/AbstractStringBuilder; +5 -1: cp855 +11 -1: Deallocator +5 -1: cp857 +5 -1: cp858 +7 -1: ([SI)[S +37 -1: ([C)Ljava/lang/AbstractStringBuilder; +27 -1: java/lang/SecurityException +82 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Class;Ljava/lang/invoke/MethodHandle;)V +38 -1: (Ljava/lang/String;)Ljava/lang/String; +7 -1: connect +7 -1: isEmpty +11 -1: replaceNode +19 -1: SuppliedThreadLocal +12 -1: asFixedArity +12 -1: fromIndex = +19 -1: createMemoryManager +9 -1: List.java +8 -1: FEBRUARY +21 -1: UnicodeLittleUnmarked +6 -1: a null +30 -1: ()Ljava/util/Spliterator; +5 -1: cp862 +17 -1: ZoneInfoFile.java +5 -1: cp866 +8 -1: BulkTask +53 -1: java/util/concurrent/locks/AbstractQueuedSynchronizer +20 -1: FileInputStream.java +12 -1: java.vm.info +10 -1: newDecoder +5 -1: (JB)V +8 -1: filePath +17 -1: spreadArrayChecks +44 -1: ([Ljava/lang/Object;Ljava/util/Comparator;)V +33 -1: java/util/Collections$AsLIFOQueue +32 -1: Ljava/util/LinkedList$Node; +5 -1: cp874 +78 -1: (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; +39 -1: (JLjava/util/function/Consumer<-TK;>;)V +15 -1: appendCodePoint +20 -1: primitiveReturnCount +54 -1: only dump output if specified permission +20 -1: getGenericInterfaces +41 -1: ([Ljava/lang/reflect/AccessibleObject;Z)V +17 -1: nUnstartedThreads +33 -1: (Ljava/lang/invoke/MemberName;Z)V +24 -1: ARRAY_OBJECT_INDEX_SCALE +40 -1: (Ljava/lang/String;ILjava/util/Locale;)I +17 -1: java/io/Flushable +22 -1: newConstructorAccessor +26 -1: sun/misc/JavaUtilJarAccess +6 -1: booted +10 -1: setDoInput +36 -1: (Ljava/lang/Class;)[Ljava/lang/Enum; +19 -1: java/lang/Character +52 -1: ([Ljava/net/URL;Ljava/net/URLStreamHandlerFactory;)V +24 -1: (Ljava/nio/LongBuffer;)I +16 -1: start > length() +28 -1: (I)Ljava/lang/CharacterData; +5 -1: val$c +61 -1: (Ljava/lang/Throwable;Ljava/lang/String;[Ljava/lang/Object;)V +13 -1: resolveOrNull +9 -1: L_ESCAPED +27 -1: MapReduceValuesToDoubleTask +15 -1: getPreparedForm +33 -1: (I)[Ljava/util/WeakHashMap$Entry; +54 -1: ()Ljava/util/stream/Stream<+Ljava/util/zip/ZipEntry;>; +16 -1: bad method type +5 -1: val$s +17 -1: Null charset name +36 -1: java/lang/invoke/LambdaForm$Compiled +24 -1: (Ljava/util/SortedMap;)V +19 -1: java/time/LocalTime +29 -1: not invocable, no method type +21 -1: recalculateWordsInUse +6 -1: val$id +39 -1: sun/security/util/ManifestEntryVerifier +60 -1: ([Ljava/lang/Class<*>;I)Ljava/lang/reflect/Constructor; +45 -1: java/util/ArrayPrefixHelpers$LongCumulateTask +5 -1: OfInt +11 -1: environment +60 -1: ([Ljava/lang/Class<*>;[B)[[Ljava/lang/annotation/Annotation; +7 -1: (JJJZ)V +10 -1: BufferPool +6 -1: isUTF8 +12 -1: threadLocals +35 -1: (Ljava/lang/String;)[Ljava/net/URL; +21 -1: Ljava/nio/LongBuffer; +15 -1: copyConstructor +25 -1: setCallSiteTargetVolatile +15 -1: getNumericValue +26 -1: Ljava/security/CodeSource; +18 -1: Null output stream +14 -1: cloneWithIndex +23 -1: LOCAL_LISTEN_PERMISSION +6 -1: (TT;)I +46 -1: (Ljava/security/PublicKey;Ljava/lang/String;)V +6 -1: setCrc +26 -1: java/io/FilterOutputStream +10 -1: access$000 +10 -1: access$001 +10 -1: access$002 +6 -1: (TT;)V +78 -1: ([TU;IILjava/lang/Class<+[TT;>;)[TT; +41 -1: java/util/concurrent/atomic/AtomicInteger +8 -1: renameTo +40 -1: (Ljava/lang/Class<*>;)Ljava/lang/Object; +17 -1: getRawAnnotations +29 -1: java/lang/VirtualMachineError +37 -1: java/lang/management/MemoryPoolMXBean +25 -1: (II)Ljava/util/List; +6 -1: utf_16 +23 -1: (Ljava/lang/String;[B)V +19 -1: MIN_ARRAY_SORT_GRAN +25 -1: array length is not legal +45 -1: java/util/concurrent/locks/ReentrantLock$Sync +36 -1: Ljava/security/AccessControlContext; +48 -1: sun/reflect/generics/repository/MethodRepository +24 -1: MethodHandleStatics.java +24 -1: addThreadDumpForMonitors +64 -1: (Ljava/util/Set;)Ljava/util/Set; +58 -1: (Ljava/lang/String;[Ljava/lang/Object;Ljava/lang/Object;)Z +37 -1: (III)Lsun/util/calendar/CalendarDate; +9 -1: createURI +15 -1: unreserveMemory +52 -1: (Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Method; +66 -1: (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType; +51 -1: (Ljava/lang/reflect/Constructor;)Ljava/lang/String; +23 -1: inheritableThreadLocals +63 -1: ()Ljava/util/Map; +16 -1: setContentLength +16 -1: LOWERCASE_LETTER +4 -1: size +25 -1: java.launcher.opt.hotspot +19 -1: buildAnnotatedTypes +26 -1: JAVAFX_LAUNCHER_CLASS_NAME +11 -1: getAliasMap +19 -1: CheckedNavigableSet +15 -1: getAbsolutePath +11 -1: doubleValue +6 -1: utf_32 +22 -1: IMPLEMENTATION_VERSION +3 -1: ne1 +11 -1: contentType +8 -1: canWrite +11 -1: Object.java +14 -1: America/Denver +8 -1: fileName +13 -1: allPermDomain +27 -1: ()Ljava/util/Iterator; +31 -1: (Lsun/reflect/MethodAccessor;)V +11 -1: asTypeCache +13 -1: lineSeparator +9 -1: JarLoader +15 -1: replacementNode +18 -1: getContentEncoding +12 -1: invoke_LLL_L +22 -1: ()Ljava/util/TimeZone; +17 -1: Reference Handler +33 -1: java/lang/invoke/MethodHandleImpl +47 -1: ()Ljava/util/concurrent/ConcurrentHashMap$Node; +12 -1: invoke_LLL_V +8 -1: form << +23 -1: (Ljava/lang/Object;JJ)J +15 -1: isHighSurrogate +31 -1: (Ljava/util/Collection<+TV;>;)Z +36 -1: ([Ljava/util/HashMap$Node;)V +23 -1: (Ljava/lang/Object;JJ)V +12 -1: utf_32be_bom +40 -1: sun/util/calendar/LocalGregorianCalendar +27 -1: [Ljava/security/CodeSigner; +15 -1: afterNodeAccess +13 -1: nextThreadNum +18 -1: INTERNED_ARGUMENTS +11 -1: getMillisOf +18 -1: offsetByCodePoints +11 -1: writeObject +48 -1: (Ljava/util/Locale$Category;Ljava/util/Locale;)V +3 -1: nfe +41 -1: (Ljava/util/Properties;Ljava/io/Reader;)V +50 -1: (Ljava/util/concurrent/CountedCompleter;[C[CIIII)V +15 -1: implFlushBuffer +33 -1: (I)[Ljava/lang/invoke/MemberName; +12 -1: Unicode.java +17 -1: DMH.invokeVirtual +5 -1: setup +51 -1: (Ljava/util/Collection;[Ljava/lang/reflect/Field;)V +3 -1: EST +7 -1: TREEBIN +7 -1: getFile +10 -1: isLeapYear +18 -1: LinkedHashIterator +14 -1: DISPLAY_SCRIPT +25 -1: privateGetDeclaredMethods +68 -1: (Ljava/util/function/Function;Ljava/lang/Object;Ljava/lang/Object;)I +22 -1: ()Ljava/util/Iterator; +21 -1: sun/management/Sensor +15 -1: getAvailableIDs +51 -1: Lsun/util/PreHashedMap; +8 -1: elot_928 +6 -1: LATIN0 +45 -1: ([Ljava/lang/Object;II[Ljava/lang/Object;II)V +10 -1: [Unlocked] +15 -1: internArguments +6 -1: LATIN9 +33 -1: (II)Ljava/lang/invoke/MethodType; +12 -1: Version.java +17 -1: setConnectTimeout +75 -1: (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String; +13 -1: highSurrogate +12 -1: Africa/Cairo +21 -1: synchronizedSortedMap +21 -1: in java.library.path +45 -1: sun/reflect/generics/tree/FormalTypeParameter +24 -1: UncaughtExceptionHandler +14 -1: previousOrSame +24 -1: java/security/Permission +9 -1: x-ISCII91 +5 -1: L_HEX +35 -1: java/lang/invoke/DirectMethodHandle +35 -1: java/util/ArrayDeque$DeqSpliterator +14 -1: java/util/List +11 -1: toLowerCase +24 -1: java/nio/charset/Charset +10 -1: MIN_NORMAL +110 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +13 -1: regionMatches +17 -1: newMethodAccessor +26 -1: (Ljava/net/InetAddress;B)V +68 -1: (Ljava/util/zip/ZipFile;Ljava/lang/String;J)Ljava/util/zip/ZipEntry; +22 -1: ()Ljava/io/FileSystem; +19 -1: primitiveSimpleName +5 -1: MOVED +9 -1: STATE_RED +13 -1: linkToSpecial +19 -1: AnnotationType.java +20 -1: (II)Ljava/util/List; +252 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;Ljava/util/function/ToDoubleBiFunction;DLjava/util/function/DoubleBinaryOperator;)V +12 -1: callSiteForm +22 -1: isSiblingBindingBefore +62 -1: ([TT;IITT;Ljava/util/Comparator<-TT;>;)I +15 -1: buildEmptyNames +11 -1: Thread.java +30 -1: Ljava/lang/ref/Reference; +35 -1: sun/reflect/MethodAccessorGenerator +152 -1: (Ljava/util/function/Function;Ljava/util/function/Function;Ljava/util/function/BinaryOperator;Ljava/util/function/Supplier;)Ljava/util/stream/Collector; +5 -1: total +242 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;Ljava/util/function/ToLongFunction;JLjava/util/function/LongBinaryOperator;)V +27 -1: javax/security/auth/Subject +43 -1: JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER +17 -1: getSignerCertPath +15 -1: registerNatives +21 -1: sun/reflect/FieldInfo +54 -1: (Ljava/nio/charset/Charset;Lsun/nio/cs/ISO_8859_1$1;)V +17 -1: unwrapWithNoPrims +17 -1: instanceof Long: +20 -1: hasRealParameterData +23 -1: ()Ljava/time/LocalTime; +14 -1: getAnnotations +8 -1: optimize +7 -1: setChar +11 -1: OFFSET_MASK +4 -1: TYPE +177 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/BiFunction;Ljava/util/concurrent/atomic/AtomicReference;)V +18 -1: removeShutdownHook +27 -1: ()Ljava/security/Principal; +29 -1: JAVAFX_APPLICATION_CLASS_NAME +6 -1: digits +37 -1: [Ljava/lang/reflect/Constructor; +45 -1: ()Ljava/lang/Thread$UncaughtExceptionHandler; +7 -1: tryLock +19 -1: java/net/Proxy$Type +21 -1: setJavaSecurityAccess +13 -1: tieBreakOrder +3 -1: no +16 -1: Australia/Sydney +13 -1: DAY_IN_MILLIS +19 -1: ()Ljava/nio/Buffer; +12 -1: Integer.java +14 -1: isBmpCodePoint +6 -1: daemon +23 -1: Lsun/misc/JavaIOAccess; +106 -1: (JLjava/util/function/BiFunction<-TK;-TV;+TU;>;Ljava/util/function/Consumer<-TU;>;)V +10 -1: getFloatAt +15 -1: content/unknown +52 -1: ()Ljava/util/Enumeration<+Ljava/util/zip/ZipEntry;>; +123 -1: (Ljava/lang/Class<*>;Lsun/reflect/annotation/AnnotationType;Lsun/reflect/annotation/AnnotationType;)Z +4 -1: nsme +12 -1: prefixLength +9 -1: flagsMods +95 -1: (BLjava/lang/invoke/MemberName;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MemberName; +62 -1: (Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/LambdaForm; +16 -1: Illegal mode: 0x +24 -1: java/io/FileOutputStream +41 -1: [Pp][Ee][Rr][Mm][Ii][Ss][Ss][Ii][Oo][Nn]= +24 -1: java/security/CodeSource +16 -1: DUMP_CLASS_FILES +25 -1: ([C)Ljava/nio/CharBuffer; +12 -1: bindArgument +50 -1: Ljava/lang/ref/FinalReference; +21 -1: unmodifiableSortedMap +10 -1: jarHandler +73 -1: (Ljava/lang/Class;[Ljava/lang/reflect/Method;)[Ljava/lang/reflect/Method; +67 -1: ()Ljava/util/Map; +15 -1: threadSeqNumber +18 -1: AutoCloseable.java +9 -1: holdsLock +25 -1: (Ljava/lang/Object;JJJJ)V +7 -1: (IJII)I +15 -1: copyToLongArray +58 -1: Ljava/util/HashMap; +84 -1: (Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; +32 -1: getExecutableTypeAnnotationBytes +17 -1: streamHandlerLock +35 -1: java/lang/IndexOutOfBoundsException +15 -1: moveRootToFront +28 -1: ()Ljava/nio/file/FileSystem; +14 -1: content-length +61 -1: (Ljava/lang/invoke/CallSite;Ljava/lang/invoke/MethodHandle;)V +7 -1: csASCII +18 -1: staticIsConsistent +21 -1: sharedToGenericString +8 -1: linkLast +21 -1: isUnicodeExtensionKey +7 -1: readInt +7 -1: compile +32 -1: ()Ljava/lang/reflect/Executable; +4 -1: Big5 +20 -1: Ljava/util/Set; +18 -1: ExpiringCache.java +44 -1: (Ljava/lang/String;[BII)Ljava/lang/Class<*>; +18 -1: LinkedHashMap.java +32 -1: Ljava/lang/UnsatisfiedLinkError; +13 -1: parameterType +28 -1: (ID)Ljava/lang/StringBuffer; +15 -1: synchronizedSet +9 -1: implClose +6 -1: member +14 -1: MH_INVOKE_MODS +21 -1: forOutputStreamWriter +37 -1: Lsun/misc/JavaIOFileDescriptorAccess; +28 -1: java/lang/ProcessEnvironment +17 -1: setNormalizedYear +14 -1: isMalformed4_2 +14 -1: isMalformed4_3 +38 -1: (Ljava/lang/Object;)Ljava/lang/String; +16 -1: getJavaAWTAccess +12 -1: isPrivileged +30 -1: java/util/Collections$EmptyMap +17 -1: LinkedKeyIterator +7 -1: vmcount +27 -1: java/lang/ref/WeakReference +5 -1: march +13 -1: addOldMapping +58 -1: (Ljava/lang/Object;Ljava/lang/Runnable;)Lsun/misc/Cleaner; +56 -1: (ILjava/lang/String;)[Ljava/lang/invoke/LambdaForm$Name; +65 -1: java/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask +55 -1: (Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object; +17 -1: getEnclosingClass +35 -1: (I)Lsun/util/calendar/BaseCalendar; +13 -1: binarySearch0 +25 -1: ([J)Ljava/nio/LongBuffer; +19 -1: java/util/Map$Entry +22 -1: java/util/HashMap$Node +26 -1: sun/reflect/MethodAccessor +8 -1: LASTYEAR +7 -1: disable +36 -1: sun/launcher/LauncherHelper$FXHelper +6 -1: toPath +10 -1: shortValue +6 -1: remove +59 -1: ([Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Process; +55 -1: java/util/concurrent/ConcurrentHashMap$ValueSpliterator +64 -1: (Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/Collection; +15 -1: asPrimitiveType +16 -1: PrintStream.java +10 -1: image/jpeg +22 -1: specificToStringHeader +7 -1: class " +38 -1: java/util/Collections$CheckedSortedMap +19 -1: SUPPRESSED_SENTINEL +16 -1: getEnumConstants +54 -1: (ILjava/lang/CharSequence;II)Ljava/lang/StringBuilder; +36 -1: Ljava/lang/Class; +13 -1: toThreadState +38 -1: (Ljava/lang/Class;)Ljava/lang/Package; +24 -1: (C)Ljava/lang/Character; +19 -1: UNTREEIFY_THRESHOLD +4 -1: NCPU +23 -1: ()Ljava/lang/Exception; +42 -1: (ITK;TV;Ljava/util/HashMap$Node;)V +15 -1: nothingToVerify +15 -1: setInitialValue +15 -1: getTimeInMillis +12 -1: getDoubleAt0 +18 -1: parameterTypeCache +86 -1: (Ljava/nio/file/WatchService;[Ljava/nio/file/WatchEvent$Kind;)Ljava/nio/file/WatchKey; +49 -1: java/util/concurrent/ConcurrentHashMap$ValuesView +13 -1: +7 -1: exitVM. +34 -1: Ljava/lang/ClassNotFoundException; +68 -1: (Ljava/util/Map;Ljava/lang/Class;)[Ljava/lang/annotation/Annotation; +28 -1: getCalendarDateFromFixedDate +28 -1: UnsafeFieldAccessorImpl.java +27 -1: java/lang/RuntimePermission +74 -1: Ljava/lang/Object;Ljava/lang/Comparable; +62 -1: ()Ljava/util/Iterator; +13 -1: LanguageRange +239 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;Ljava/util/function/ToIntFunction;ILjava/util/function/IntBinaryOperator;)V +37 -1: DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE +62 -1: (Ljava/lang/invoke/MethodType;II)Ljava/lang/invoke/MethodType; +16 -1: DMH.invokeStatic +11 -1: (TK;TV;)TV; +7 -1: ([FI)[F +14 -1: newPerfCounter +35 -1: ([JI)Ljava/util/Spliterator$OfLong; +30 -1: java/util/AbstractList$ListItr +5 -1: cp912 +5 -1: cp914 +45 -1: (Ljava/io/BufferedWriter;Ljava/lang/String;)V +6 -1: LOCNAM +8 -1: launcher +5 -1: cp915 +14 -1: standardString +26 -1: ()Ljava/lang/Thread$State; +10 -1: L_ALPHANUM +8 -1: (C[CII)I +9 -1: SEPTEMBER +20 -1: java/text/DateFormat +38 -1: Ljava/lang/CloneNotSupportedException; +5 -1: cp920 +23 -1: getConstructorSignature +16 -1: ReferenceHandler +19 -1: America/Puerto_Rico +5 -1: cp923 +10 -1: typeString +30 -1: Self-suppression not permitted +25 -1: (Ljava/io/OutputStream;)V +9 -1: implReset +12 -1: fullAddCount +34 -1: java/lang/invoke/LambdaForm$Hidden +25 -1: ()Lsun/misc/JavaIOAccess; +9 -1: Math.java +9 -1: getAndSet +7 -1: failure +14 -1: LINE_SEPARATOR +6 -1: parent +30 -1: java/lang/BootstrapMethodError +8 -1: indexMap +9 -1: ALL_KINDS +23 -1: desiredAssertionStatus0 +39 -1: (ILjava/lang/Object;)Ljava/lang/Object; +22 -1: RuntimePermission.java +21 -1: getContextClassLoader +14 -1: VARARGS_INVOKE +8 -1: zoneinfo +130 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;Ljava/lang/invoke/MemberName;ILjava/lang/invoke/DirectMethodHandle$1;)V +18 -1: java/lang/Readable +11 -1: containsAll +11 -1: newPosition +57 -1: sun/reflect/InstantiationExceptionConstructorAccessorImpl +13 -1: REVERSE_ORDER +29 -1: Required array size too large +6 -1: sunday +44 -1: ()Ljava/util/Set; +10 -1: toIntExact +33 -1: ([BIILjava/nio/charset/Charset;)V +14 -1: indexOfSubList +15 -1: tryAcquireNanos +31 -1: java/lang/InvalidClassException +22 -1: SecureClassLoader.java +12 -1: proxiedHosts +7 -1: ([CII)I +11 -1: toHexString +30 -1: sun/util/calendar/ZoneInfoFile +31 -1: Ljava/util/jar/Attributes$Name; +10 -1: L_USERINFO +25 -1: (IB)Ljava/nio/ByteBuffer; +11 -1: parseDouble +7 -1: ([CII)V +13 -1: Asia/Shanghai +5 -1: [...] +57 -1: ([Ljava/lang/Class;[B)[[Ljava/lang/annotation/Annotation; +19 -1: java/nio/LongBuffer +15 -1: getCertificates +9 -1: comparing +83 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Class<*>;IILjava/lang/String;[B)V +43 -1: Ljava/util/concurrent/atomic/AtomicInteger; +23 -1: toFieldDescriptorString +20 -1: Lsun/misc/MetaIndex; +37 -1: java/util/Collections$UnmodifiableSet +5 -1: (JC)V +37 -1: nanosecond timeout value out of range +26 -1: AbstractStringBuilder.java +43 -1: java/lang/invoke/DirectMethodHandle$Special +49 -1: ([Ljava/nio/file/LinkOption;)Ljava/nio/file/Path; +15 -1: currentPosition +14 -1: java/net/Proxy +13 -1: asConstructor +8 -1: userInfo +14 -1: parseClassPath +15 -1: legacyMergeSort +34 -1: java/security/UnresolvedPermission +97 -1: Lsun/util/locale/LocaleObjectCache; +9 -1: freeEntry +19 -1: delimiterCodePoints +34 -1: Should be non-empty if initialized +23 -1: (I)Ljava/lang/Class<*>; +11 -1: Reader.java +26 -1: checkClassLoaderPermission +27 -1: java/nio/DirectShortBufferS +95 -1: Ljava/lang/Object;Ljava/security/PrivilegedExceptionAction; +27 -1: java/nio/DirectShortBufferU +20 -1: ()[Ljava/lang/Class; +56 -1: ()[Ljava/util/concurrent/ConcurrentHashMap$Node; +19 -1: sun/nio/cs/UTF_16BE +24 -1: java/util/AbstractList$1 +10 -1: ([CIIIII)V +60 -1: Ljava/lang/Object;Ljava/lang/Comparable; +37 -1: (Ljava/lang/invoke/LambdaForm$Name;)S +9 -1: putDouble +52 -1: ([Ljava/security/CodeSource;)Ljava/util/Enumeration; +37 -1: (Ljava/lang/invoke/LambdaForm$Name;)Z +22 -1: ()[Ljava/lang/Package; +41 -1: java/lang/CharSequence$1CodePointIterator +13 -1: auditSubclass +24 -1: Ljava/util/jar/JarEntry; +20 -1: findMethodHandleType +15 -1: MAX_BUFFER_SIZE +19 -1: FilePermission.java +18 -1: WrappedPrintStream +36 -1: (D)Ljava/lang/AbstractStringBuilder; +11 -1: unfinalized +10 -1: getFileURL +37 -1: (Ljava/io/FileFilter;)[Ljava/io/File; +54 -1: (Ljava/nio/ByteBuffer;I)Ljava/nio/charset/CoderResult; +7 -1: ([ZI)[Z +64 -1: (Ljava/security/CodeSource;)Ljava/security/PermissionCollection; +6 -1: PUBLIC +83 -1: (Ljava/util/jar/JarFile;Ljava/net/URL;Ljava/lang/String;)Ljava/security/CodeSource; +17 -1: lockInterruptibly +67 -1: ([Ljava/util/Hashtable$Entry;Ljava/lang/Object;Ljava/lang/Object;)V +42 -1: java/util/ArraysParallelSortHelpers$FJChar +21 -1: defaultCharBufferSize +14 -1: unalignedKnown +23 -1: ()Ljava/net/Proxy$Type; +4 -1: TZDB +14 -1: CharacterCache +13 -1: lengthOfMonth +13 -1: hasExtensions +23 -1: Prefix string too short +15 -1: Executable.java +10 -1: forEachKey +6 -1: getEra +13 -1: appendEncoded +21 -1: java/util/AbstractMap +10 -1: access$100 +10 -1: access$102 +30 -1: javafx.application.Application +46 -1: (Ljava/lang/Thread$UncaughtExceptionHandler;)V +43 -1: Ljava/lang/invoke/LambdaForm$NamedFunction; +101 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;IILjava/lang/String;[B)Ljava/lang/reflect/Field; +9 -1: WILD_CHAR +21 -1: SynchronizedSortedSet +28 -1: (Ljava/util/Collection<*>;)Z +29 -1: (I[C)Ljava/lang/StringBuffer; +65 -1: (Ljava/lang/String;[Ljava/lang/Class;Z)Ljava/lang/reflect/Method; +7 -1: putByte +6 -1: H_MARK +49 -1: (Ljava/lang/invoke/MemberName;)Ljava/lang/Object; +98 -1: ([Ljava/lang/ClassValue$Entry<*>;ILjava/lang/ClassValue$Entry<*>;Z)Ljava/lang/ClassValue$Entry<*>; +23 -1: array is not of length +52 -1: (Ljava/util/List;TT;TT;)Z +41 -1: Ljava/util/Collections$EmptyListIterator; +8 -1: +11 -1: updateCheck +29 -1: getBootClassPathEntryForClass +27 -1: sun/nio/cs/US_ASCII$Encoder +10 -1: bindCaller +18 -1: Ljava/util/BitSet; +10 -1: checkRange +77 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Class<*>;Ljava/lang/Void;)V +7 -1: Classes +6 -1: store0 +23 -1: java/lang/Thread$Caches +25 -1: Ljava/lang/CharacterData; +7 -1: (JI[C)V +49 -1: (Ljava/util/LinkedList;Ljava/util/LinkedList$1;)V +16 -1: getGcInfoBuilder +12 -1: counterCells +14 -1: memoryLimitSet +7 -1: , nojit +9 -1: sharpsMap +7 -1: october +13 -1: isProxiedHost +9 -1: rawOffset +18 -1: toJavaFormatString +19 -1: sun.boot.class.path +60 -1: (ILjava/lang/CharSequence;)Ljava/lang/AbstractStringBuilder; +11 -1: spliterator +13 -1: contentLength +18 -1: unixTimeToFileTime +31 -1: Lsun/reflect/LangReflectAccess; +16 -1: while Java has +79 -1: (JLjava/util/function/ToIntBiFunction;ILjava/util/function/IntBinaryOperator;)I +12 -1: timeEndOfDay +17 -1: getCustomTimeZone +25 -1: Ljava/lang/ref/Reference; +20 -1: ()Ljava/util/Locale; +64 -1: (Ljava/util/HashMap;[Ljava/util/HashMap$Node;Z)V +13 -1: MAX_JVM_ARITY +72 -1: (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/invoke/MethodType; +11 -1: AsLIFOQueue +84 -1: (Ljava/util/List;Ljava/lang/Object;)Ljava/util/List; +12 -1: mappingCount +29 -1: (Ljava/io/FileOutputStream;)V +50 -1: (Ljava/util/List<-TT;>;TT;)V +23 -1: Category cannot be NULL +10 -1: normalized +5 -1: CLASS +28 -1: (IZ)Ljava/lang/StringBuffer; +18 -1: java/lang/System$1 +18 -1: java/lang/System$2 +9 -1: getResult +44 -1: ()Ljava/util/Collection; +8 -1: isNative +59 -1: Ljava/lang/Number;Ljava/lang/Comparable; +24 -1: [Ljava/lang/ThreadGroup; +24 -1: (B)Ljava/nio/ByteBuffer; +4 -1: READ +44 -1: (Ljava/io/FilePermission;)Ljava/lang/String; +93 -1: Ljava/util/Collections$SynchronizedCollection;Ljava/util/Set; +12 -1: compileClass +12 -1: isProxyClass +20 -1: isSystemDomainLoader +74 -1: (Ljava/util/List;Ljava/util/Comparator<-TT;>;)V +7 -1: getMask +72 -1: (Ljava/lang/ClassLoader;Ljava/lang/SecurityManager;Ljava/lang/String;I)V +20 -1: removeLastOccurrence +64 -1: (Ljava/lang/reflect/Field;)Ljava/lang/invoke/DirectMethodHandle; +57 -1: ()Ljava/util/Map;>; +11 -1: parkBlocker +40 -1: (Lsun/misc/JarIndex;Ljava/lang/String;)V +33 -1: [Ljava/security/ProtectionDomain; +14 -1: setContentType +14 -1: getEnumeration +18 -1: ProtectionDomain +76 -1: (Lsun/util/calendar/BaseCalendar$Date;)Lsun/util/calendar/BaseCalendar$Date; +16 -1: setRequestMethod +52 -1: (Ljava/util/List;Ljava/lang/Object;)Ljava/util/List; +32 -1: Lsun/util/calendar/BaseCalendar; +52 -1: (Ljava/net/URL;Ljava/lang/String;)Ljava/lang/String; +5 -1: .:@[] +7 -1: addLast +21 -1: AnnotatedElement.java +10 -1: defaultVal +16 -1: getCanonicalPath +17 -1: protection_domain +9 -1: strictfp +19 -1: sun/nio/cs/UTF_16LE +9 -1: readBytes +18 -1: removeStaleEntries +46 -1: java/util/Collections$UnmodifiableNavigableSet +5 -1: cpath +14 -1: COPY_THRESHOLD +8 -1: permsMap +8 -1: japanese +33 -1: java/nio/charset/StandardCharsets +47 -1: Lsun/reflect/DelegatingConstructorAccessorImpl; +19 -1: NF_checkGenericType +40 -1: java/util/Collections$UnmodifiableList$1 +4 -1: TERM +48 -1: The following can be used with stack and domain: +27 -1: ([BII)Ljava/nio/ByteBuffer; +40 -1: Ljava/util/Vector;>; +5 -1: digit +7 -1: isFinal +39 -1: (Ljava/lang/String;Ljava/lang/String;)I +26 -1: memberDeclaringClassOrNull +10 -1: ([CI[BII)I +38 -1: (Ljava/lang/Class;I)Ljava/lang/Object; +15 -1: isValidProtocol +17 -1: (this Collection) +11 -1: getTreeNode +16 -1: ThreadLocal.java +23 -1: java/nio/HeapLongBuffer +39 -1: (Ljava/lang/String;Ljava/lang/String;)V +12 -1: getNextEntry +39 -1: (Ljava/lang/String;Ljava/lang/String;)Z +28 -1: (C)Lsun/invoke/util/Wrapper; +9 -1: readFloat +21 -1: overrideFieldAccessor +16 -1: fillInStackTrace +16 -1: getDeclaredField +5 -1: deflt +8 -1: nextChar +10 -1: primCounts +22 -1: getAnnotatedInterfaces +26 -1: ()Ljava/util/zip/Inflater; +73 -1: (JLjava/util/function/BiFunction<-TK;-TV;+TU;>;)TU; +16 -1: traceMethodCalls +10 -1: sun.nio.cs +7 -1: marshal +9 -1: ftypeKind +77 -1: (Ljava/lang/invoke/MemberName;Ljava/lang/Class;)Ljava/lang/invoke/MemberName; +11 -1: sun/misc/VM +14 -1: GuardWithCatch +40 -1: (Ljava/lang/Object;)Ljava/util/Iterator; +13 -1: subtractExact +42 -1: (Ljava/lang/Object;ILjava/lang/Object;II)V +10 -1: isInfinite +18 -1: sun.util.calendar. +14 -1: java/lang/Math +16 -1: java/lang/String +10 -1: encodePath +14 -1: compactAndTrim +11 -1: getVariants +4 -1: from +47 -1: (Ljava/lang/ThreadLocal<*>;Ljava/lang/Object;)V +35 -1: serializeAgentPropertiesToByteArray +16 -1: computeIfPresent +9 -1: EMPTY_MAP +28 -1: java/lang/InstantiationError +68 -1: (Ljava/util/Comparator;Ljava/util/Comparator;)Ljava/util/Comparator; +14 -1: getDisplayName +14 -1: limitedContext +23 -1: usagetracker.properties +52 -1: java/util/concurrent/locks/ReentrantLock$NonfairSync +7 -1: public +17 -1: srcBegin > srcEnd +48 -1: (ILjava/util/List;)Ljava/lang/invoke/MethodType; +21 -1: java/lang/ThreadDeath +9 -1: gregorian +111 -1: (Ljava/util/HashMap;[Ljava/util/HashMap$Node;ILjava/lang/Object;Ljava/lang/Object;)Ljava/util/HashMap$TreeNode; +52 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;III)V +12 -1: generateFile +20 -1: appendParameterTypes +22 -1: sun/misc/FileURLMapper +13 -1: defaultDomain +25 -1: (I)Ljava/time/ZoneOffset; +21 -1: getBooleanAttributes0 +39 -1: (Ljava/lang/String;)Lsun/misc/Resource; +43 -1: Ljava/lang/Thread$UncaughtExceptionHandler; +23 -1: getTypeAnnotationBytes0 +8 -1: ELOT_928 +32 -1: sun/nio/cs/FastCharsetProvider$1 +34 -1: Ljava/nio/BufferOverflowException; +14 -1: AppClassLoader +10 -1: protected +12 -1: isAnnotation +16 -1: PerfCounter.java +51 -1: Ljava/util/Map; +160 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +11 -1: setLeapYear +16 -1: parseContextSpec +16 -1: setFieldAccessor +8 -1: writeInt +16 -1: java/lang/Number +33 -1: java/util/AbstractMap$SimpleEntry +9 -1: nextTable +8 -1: getQuery +14 -1: putOrderedLong +93 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +52 -1: (Ljava/lang/String;)Lsun/reflect/generics/tree/Tree; +85 -1: (ILjava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap$Node;)V +9 -1: singleton +9 -1: destroyed +15 -1: iso_8859-2:1987 +12 -1: comparingInt +29 -1: [Ljava/lang/OutOfMemoryError; +39 -1: (Ljava/lang/String;Ljava/lang/Object;)V +27 -1: ([Ljava/util/Enumeration;)V +36 -1: Ljava/nio/charset/CodingErrorAction; +16 -1: getCanonicalName +41 -1: (Ljava/nio/LongBuffer;)Ljava/util/BitSet; +15 -1: DISPLAY_COUNTRY +32 -1: getFunctionalInterfaceMethodName +66 -1: (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V +24 -1: getUnresolvedPermissions +66 -1: ([Ljava/lang/ClassValue$Entry<*>;I)Ljava/lang/ClassValue$Entry<*>; +41 -1: ()Lsun/reflect/annotation/AnnotationType; +7 -1: afIndex +7 -1: csascii +20 -1: ()Ljava/util/Vector; +16 -1: EntrySpliterator +53 -1: (Ljava/lang/Throwable;I)Ljava/lang/StackTraceElement; +81 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; +20 -1: classAssertionStatus +7 -1: EXECUTE +21 -1: ()Ljava/lang/Runtime; +6 -1: cesu-8 +7 -1: offset +23 -1: Ljava/lang/SafeVarargs; +34 -1: (Ljava/util/LinkedHashMap$Entry;)V +8 -1: entryFor +8 -1: getCache +46 -1: (Ljava/lang/Object;I)Ljava/lang/reflect/Field; +4 -1: skip +8 -1: (II[CI)V +4 -1: vart +12 -1: InnerClasses +68 -1: (Ljava/util/Map;Ljava/lang/Class;[Ljava/lang/String;)Ljava/util/Map; +19 -1: currentClassLoader0 +34 -1: getDefaultUncaughtExceptionHandler +11 -1: String.java +117 -1: (Ljava/lang/ThreadLocal<*>;ILjava/lang/ThreadLocal$ThreadLocalMap$Entry;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry; +7 -1: january +31 -1: (ILjava/lang/String;IIIIIIIII)V +24 -1: Lsun/misc/JavaAWTAccess; +5 -1: .path +15 -1: [Ljava/io/File; +11 -1: Writer.java +8 -1: , Size: +159 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/function/Consumer;)V +32 -1: java/lang/invoke/LambdaForm$Name +51 -1: (Ljava/util/ArrayList;Ljava/util/AbstractList;III)V +7 -1: getZone +14 -1: JIS_X0212-1990 +21 -1: (Ljava/util/Set<*>;)Z +149 -1: (Lsun/util/locale/provider/LocaleServiceProviderPool$LocalizedObjectGetter;Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; +21 -1: Illegal Load factor: +35 -1: ()Ljava/lang/invoke/MethodTypeForm; +22 -1: ([Z)Ljava/lang/String; +7 -1: setName +48 -1: (TT;Ljava/lang/String;)TT; +9 -1: INTERFACE +22 -1: ARRAY_CHAR_INDEX_SCALE +19 -1: java/nio/ByteBuffer +23 -1: Ljava/io/ExpiringCache; +7 -1: streams +44 -1: java/lang/invoke/DirectMethodHandle$Accessor +36 -1: ([Ljava/security/ProtectionDomain;)V +16 -1: afterNodeRemoval +9 -1: prevIndex +49 -1: java/util/concurrent/ConcurrentHashMap$KeySetView +22 -1: getEnumConstantsShared +17 -1: java/lang/Integer +12 -1: getRawOffset +36 -1: ()Ljava/nio/file/attribute/FileTime; +7 -1: offsets +10 -1: ] throw => +3 -1: [[B +10 -1: hostsEqual +18 -1: compareComparables +35 -1: sun/reflect/ConstructorAccessorImpl +8 -1: december +36 -1: Invalid binary time-zone data: TZDB: +24 -1: synchronizedNavigableMap +72 -1: sun/util/locale/provider/LocaleServiceProviderPool$LocalizedObjectGetter +19 -1: parseCustomTimeZone +88 -1: (Ljava/lang/Class<*>;Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/DirectMethodHandle; +9 -1: findClass +6 -1: OBJECT +3 -1: GBK +110 -1: (JLjava/util/function/ToLongFunction;>;JLjava/util/function/LongBinaryOperator;)J +6 -1: UTF_16 +17 -1: +13 -1: lookupCharset +28 -1: ConstructorAccessorImpl.java +62 -1: java/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask +30 -1: Ljava/lang/ClassCastException; +56 -1: ()Ljava/util/Spliterator;>; +11 -1: invokerType +23 -1: java/lang/StringBuilder +12 -1: deleteCharAt +11 -1: CR_OVERFLOW +14 -1: toExternalForm +3 -1: out +34 -1: Ljava/net/URLStreamHandlerFactory; +15 -1: encodeArrayLoop +30 -1: ()Ljava/util/Enumeration; +27 -1: java/io/SyncFailedException +10 -1: checkedSet +16 -1: checkedSortedSet +22 -1: java/util/zip/ZipEntry +43 -1: java/util/LinkedHashMap$LinkedValueIterator +22 -1: UnmodifiableCollection +32 -1: java/nio/ByteBufferAsCharBufferB +11 -1: blockerLock +27 -1: checkExtensionsDependencies +11 -1: fromIndex: +32 -1: java/nio/ByteBufferAsCharBufferL +6 -1: UTF_32 +30 -1: java/util/Hashtable$Enumerator +92 -1: (Ljava/util/Map<+TK;+TV;>;)Ljava/util/Map; +4 -1: tail +5 -1: (BB)C +16 -1: isValidSignature +9 -1: addMillis +9 -1: peekFirst +86 -1: (Ljava/util/Set;Ljava/lang/Class;)Ljava/util/Set; +5 -1: (BB)I +15 -1: jvmMicroVersion +28 -1: [Ljava/util/Hashtable$Entry; +15 -1: iso_8859-5:1988 +14 -1: HOUR_IN_MILLIS +67 -1: (Ljava/util/PrimitiveIterator$OfInt;I)Ljava/util/Spliterator$OfInt; +5 -1: (BB)S +21 -1: UnmodifiableSortedMap +79 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap;)V +56 -1: Ljava/util/Stack; +5 -1: (BB)Z +10 -1: treeifyBin +8 -1: isOpaque +27 -1: java.launcher.ergo.message1 +27 -1: java.launcher.ergo.message2 +101 -1: Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Cloneable;Ljava/lang/Comparable; +31 -1: (Ljava/io/ObjectOutputStream;)V +3 -1: GET +13 -1: matchLocation +13 -1: WrappedMember +63 -1: NoSuchMethodException:\n could not find proper constructor for +14 -1: gssloginconfig +70 -1: (Ljava/util/LinkedList$Node;TE;Ljava/util/LinkedList$Node;)V +57 -1: (Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object; +11 -1: toByteArray +49 -1: java/util/ArraysParallelSortHelpers$FJByte$Sorter +13 -1: no protocol: +940 -1: aaaarababkaeaveafafrakakaamamhanargararaasasmavavaayaymazazebabakbebelbgbulbhbihbibisbmbambnbenbobodbrbrebsboscacatcechechchacocoscrcrecscescuchucvchvcycymdadandedeudvdivdzdzoeeeweelellenengeoepoesspaetesteueusfafasfffulfifinfjfijfofaofrfrafyfrygaglegdglaglglggngrngugujgvglvhahauhehebhihinhohmohrhrvhthathuhunhyhyehzheriainaidindieileigiboiiiiiikipkinindioidoisislititaiuikuiwhebjajpnjiyidjvjavkakatkgkonkikikkjkuakkkazklkalkmkhmknkankokorkrkaukskaskukurkvkomkwcorkykirlalatlbltzlgluglilimlnlinlolaoltlitlulublvlavmgmlgmhmahmimrimkmkdmlmalmnmonmomolmrmarmsmsamtmltmymyananaunbnobndndenenepngndonlnldnnnnononornrnblnvnavnynyaocociojojiomormororiososspapanpipliplpolpspusptporququermrohrnrunroronrurusrwkinsasanscsrdsdsndsesmesgsagsisinskslkslslvsmsmosnsnasosomsqsqisrsrpsssswstsotsusunsvsweswswatatamteteltgtgkththatitirtktuktltgltntsntotontrturtstsotttattwtwitytahuguigukukrururduzuzbvevenvivievovolwawlnwowolxhxhoyiyidyoyorzazhazhzhozuzul +42 -1: java/util/LinkedHashMap$LinkedHashIterator +39 -1: java/util/ArrayDeque$DescendingIterator +15 -1: MODIFIER_LETTER +21 -1: (Lsun/misc/Cleaner;)Z +12 -1: PACKAGE_NAME +14 -1: getMappedValue +10 -1: interrupt0 +8 -1: LF_LIMIT +17 -1: getDeclaringClass +42 -1: (ZILjava/lang/String;)Ljava/lang/Class<*>; +57 -1: (Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;[I)V +15 -1: java/nio/Bits$1 +61 -1: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class; +28 -1: java/lang/ref/ReferenceQueue +33 -1: [Ljava/security/cert/Certificate; +44 -1: (Ljava/util/Hashtable;I)Ljava/util/Iterator; +24 -1: java/security/CodeSigner +19 -1: Non-positive length +24 -1: [Ljava/util/Enumeration; +38 -1: ()Ljava/security/PermissionCollection; +16 -1: checkGenericType +56 -1: java/util/concurrent/ConcurrentHashMap$ReduceEntriesTask +7 -1: getYear +5 -1: atime +19 -1: Ljava/util/HashMap; +125 -1: (JLjava/util/function/Function;+TU;>;Ljava/util/function/Consumer<-TU;>;)V +22 -1: STOP_THREAD_PERMISSION +46 -1: (Ljava/util/Enumeration;)Ljava/util/ArrayList; +16 -1: getPathSeparator +10 -1: getMembers +8 -1: getIntAt +26 -1: java/io/File$TempDirectory +48 -1: java/lang/invoke/MethodHandleImpl$GuardWithCatch +25 -1: CaseInsensitiveComparator +8 -1: pollLast +21 -1: GET_POLICY_PERMISSION +23 -1: uninitialized call site +75 -1: (Ljava/util/function/Function;Ljava/util/Comparator;)Ljava/util/Comparator; +9 -1: directory +51 -1: (JLjava/util/function/BiFunction<-TV;-TV;+TV;>;)TV; +41 -1: (Ljava/lang/ThreadLocal$ThreadLocalMap;)V +42 -1: (Ljava/lang/Throwable;Ljava/lang/String;)V +26 -1: (FLjava/lang/Appendable;)V +5 -1: stop0 +9 -1: substring +64 -1: (ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)V +5 -1: (JD)V +9 -1: getShortB +10 -1: nextOrSame +24 -1: [ interpretWithArguments +6 -1: GB2312 +32 -1: java/nio/BufferOverflowException +23 -1: sun/nio/cs/ArrayEncoder +4 -1: tanh +9 -1: getShortL +55 -1: (JLjava/util/function/BiFunction;)Ljava/util/Map$Entry; +10 -1: getMessage +12 -1: findTreeNode +38 -1: DIRECTIONALITY_COMMON_NUMBER_SEPARATOR +23 -1: [Ljava/lang/Comparable; +17 -1: getCallSiteTarget +55 -1: (Ljava/nio/ByteBuffer;II)Ljava/nio/charset/CoderResult; +19 -1: java/util/ArrayList +17 -1: java/io/DataInput +13 -1: getPrincipals +52 -1: (TE;)Ljava/util/Iterator; +44 -1: sun/reflect/generics/tree/ClassTypeSignature +6 -1: loaded +20 -1: ()Ljava/lang/Object; +36 -1: Ljava/util/concurrent/ConcurrentMap; +13 -1: classValueMap +33 -1: java/lang/SystemClassLoaderAction +6 -1: loader +31 -1: java/lang/annotation/Annotation +5 -1: colon +11 -1: Vector.java +24 -1: CharacterDataLatin1.java +12 -1: setUseCaches +22 -1: getTypeAnnotationBytes +9 -1: readShort +24 -1: longPrimitiveReturnCount +5 -1: get16 +34 -1: setDefaultUncaughtExceptionHandler +17 -1: cachedInputStream +29 -1: java/util/LinkedHashMap$Entry +17 -1: java/lang/Boolean +50 -1: ()[Lsun/reflect/generics/tree/FormalTypeParameter; +14 -1: AnnotationData +21 -1: Ljava/net/Proxy$Type; +13 -1: invokeVirtual +14 -1: Parameter.java +21 -1: getDayOfWeekDateAfter +92 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +56 -1: (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +46 -1: sun/util/locale/provider/LocaleProviderAdapter +29 -1: Ljava/lang/StackTraceElement; +47 -1: (TK;Ljava/util/function/Function<-TK;+TV;>;)TV; +32 -1: enableContextClassLoaderOverride +68 -1: (Ljava/lang/AbstractStringBuilder;)Ljava/lang/AbstractStringBuilder; +51 -1: Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +9 -1: addAndGet +5 -1: store +7 -1: ([JII)V +15 -1: signatureReturn +18 -1: NF_reinvokerTarget +22 -1: ()Ljava/nio/file/Path; +25 -1: (C)Ljava/lang/Appendable; +7 -1: expires +18 -1: initializeInvokers +19 -1: application/java-vm +13 -1: stopOrSuspend +13 -1: rawOffsetDiff +6 -1: (JJZ)V +9 -1: findValue +5 -1: get32 +10 -1: asSubclass +6 -1: forJRE +3 -1: GMT +7 -1: delete0 +69 -1: ([Ljava/security/cert/Certificate;[Ljava/security/cert/Certificate;)Z +75 -1: (Ljava/util/LinkedList$Node;Ljava/lang/Object;Ljava/util/LinkedList$Node;)V +6 -1: setEra +24 -1: ()Ljava/util/Comparator; +10 -1: access$200 +10 -1: access$202 +20 -1: retrieveDisplayNames +3 -1: pae +24 -1: java/lang/Byte$ByteCache +7 -1: VM.java +9 -1: TRANSIENT +6 -1: setErr +16 -1: jdkUpdateVersion +10 -1: isResolved +35 -1: sun/misc/JavaIOFileDescriptorAccess +4 -1: char +13 -1: Readable.java +19 -1: UnixFileSystem.java +43 -1: (Ljava/lang/ThreadLocal;)Ljava/lang/Object; +40 -1: (Ljava/lang/String;[Ljava/lang/String;)V +7 -1: profile +11 -1: , version: +25 -1: PermissionCollection.java +13 -1: setNormalized +10 -1: access$210 +24 -1: (Ljava/lang/String;IJZ)J +19 -1: isAnnotationPresent +85 -1: (Ljava/util/Map;Ljava/lang/Class;Ljava/lang/Class;)[Ljava/lang/annotation/Annotation; +19 -1: DMH.invokeInterface +157 -1: Ljava/util/concurrent/ConcurrentHashMap$CollectionView;Ljava/util/Collection;Ljava/io/Serializable; +94 -1: Ljava/util/Collections$UnmodifiableCollection;Ljava/util/List; +41 -1: java/lang/StringIndexOutOfBoundsException +29 -1: java/net/UnknownHostException +11 -1: (BBBBBBBB)J +4 -1: iioe +12 -1: (TK;TV;Z)TV; +5 -1: ERROR +31 -1: (Ljava/io/File;Ljava/io/File;)I +32 -1: [Ljava/lang/invoke/MethodHandle; +27 -1: lambda$comparing$77a9974f$1 +13 -1: toLowerCaseEx +61 -1: (Ljava/lang/invoke/LambdaForm;Ljava/lang/invoke/MemberName;)V +66 -1: (ILjava/lang/Object;Ljava/lang/Class;)Ljava/util/HashMap$TreeNode; +43 -1: java/util/concurrent/ConcurrentHashMap$Node +23 -1: latestUserDefinedLoader +24 -1: buildAnnotatedSuperclass +19 -1: compareToIgnoreCase +31 -1: (Ljava/io/File;Ljava/io/File;)Z +40 -1: (I[C)[Ljava/lang/invoke/LambdaForm$Name; +16 -1: ROTATE_THRESHOLD +18 -1: getClassAtIfLoaded +37 -1: java/lang/IllegalThreadStateException +5 -1: get64 +12 -1: writeReplace +14 -1: DAYS_PER_CYCLE +4 -1: _get +6 -1: nChars +26 -1: ()Ljava/net/SocketAddress; +27 -1: setUncaughtExceptionHandler +6 -1: jzfile +42 -1: All subclasses should override this method +3 2: Foo +56 -1: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +136 -1: (Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;[Ljava/security/Permission;)TT; +3 -1: pdt +44 -1: sun/util/locale/LocaleObjectCache$CacheEntry +20 -1: java/util/Comparator +9 -1: suspended +11 -1: removeEntry +10 -1: SPACE_FREE +12 -1: processQueue +9 -1: java.home +5 -1: valid +23 -1: printEnclosedStackTrace +4 -1: push +5 -1: guard +23 -1: javaNetHttpCookieAccess +36 -1: (Ljava/security/cert/Certificate;)[B +9 -1: isWrapped +12 -1: CharIterator +26 -1: sun.io.useCanonPrefixCache +42 -1: (Lsun/misc/Cleaner;Ljava/lang/Throwable;)V +7 -1: prepare +8 -1: parseInt +13 -1: Invokers.java +63 -1: (Ljava/net/URLClassLoader;)Ljava/security/AccessControlContext; +18 -1: defaultWriteObject +5 -1: class +15 -1: EnclosingMethod +23 -1: ([BI)Ljava/lang/String; +16 -1: rangeCheckForAdd +11 -1: getTimeImpl +15 -1: arrayIndexScale +5 -1: scalb +5 -1: scale +45 -1: (Ljava/lang/String;J)Ljava/util/zip/ZipEntry; +8 -1: ([FIIF)I +16 -1: runAllFinalizers +27 -1: ()Lsun/net/ProgressMonitor; +15 -1: MemberName.java +27 -1: [Ljava/lang/reflect/Member; +6 -1: length +14 -1: genericInvoker +8 -1: ([FIIF)V +34 -1: Ljava/nio/file/attribute/FileTime; +6 -1: number +70 -1: (Ljava/lang/StringBuilder;Ljava/lang/String;)Ljava/lang/StringBuilder; +12 -1: printLocales +38 -1: java/lang/invoke/MethodHandleStatics$1 +8 -1: private +20 -1: invalid actions mask +10 -1: not found +13 -1: parseClassSig +22 -1: getAllAvailableLocales +175 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/concurrent/atomic/AtomicReference;)V +8 -1: ([BII)[B +35 -1: (Ljava/util/HashMap$Node;)V +132 -1: (Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;[Ljava/lang/Object;[I[Ljava/lang/Object;)V +8 -1: ([BII)[C +20 -1: DECIMAL_DIGIT_NUMBER +40 -1: (Ljava/lang/String;[Ljava/lang/Object;)Z +7 -1: ([CCI)I +64 -1: (TV;)Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +8 -1: aliasMap +8 -1: checkfpx +44 -1: java/util/Comparators$NaturalOrderComparator +48 -1: (Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader; +12 -1: Name is null +10 -1: invoke_L_L +8 -1: URL.java +51 -1: (JILjava/time/ZoneOffset;)Ljava/time/LocalDateTime; +25 -1: Lsun/invoke/util/Wrapper; +19 -1: LauncherHelper.java +10 -1: invoke_L_V +5 -1: index +30 -1: sun/security/x509/X509CertImpl +8 -1: addClass +46 -1: (I)Ljava/lang/invoke/LambdaForm$NamedFunction; +20 -1: refKindIsConstructor +10 -1: getFieldAt +5 -1: log10 +13 -1: GetPerfAction +15 -1: isLetterOrDigit +27 -1: hasCheckedSpecialAttributes +25 -1: MapReduceEntriesToIntTask +17 -1: probeHomeLocation +9 -1: image/png +19 -1: checkSpreadArgument +12 -1: LinkedKeySet +13 -1: removeMapping +39 -1: sun/security/util/SecurityConstants$AWT +9 -1: MAX_RADIX +28 -1: (F)Ljava/lang/StringBuilder; +11 -1: ([C[B[I[I)Z +36 -1: (Ljava/lang/Class;)Ljava/lang/Class; +32 -1: java/lang/invoke/MagicLambdaImpl +6 -1: monday +16 -1: closeClassLoader +41 -1: (Ljava/util/concurrent/locks/Condition;)I +8 -1: reversed +27 -1: sun/util/calendar/Gregorian +49 -1: (Lsun/nio/cs/FastCharsetProvider;)Ljava/util/Map; +42 -1: (Ljava/lang/String;Ljava/lang/Throwable;)V +18 -1: java/util/Calendar +8 -1: vmtarget +17 -1: TREEIFY_THRESHOLD +41 -1: (Ljava/util/concurrent/locks/Condition;)Z +9 -1: deadChild +8 -1: EntrySet +5 -1: log1p +58 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/util/HashMap;)V +9 -1: pageCount +14 -1: slotToArgTable +24 -1: toMethodDescriptorString +25 -1: ([B)Ljava/nio/ByteBuffer; +21 -1: twoToTheDoubleScaleUp +32 -1: sun/misc/URLClassPath$FileLoader +40 -1: (Ljava/util/List;Z)V +6 -1: cache1 +6 -1: cache2 +27 -1: Ljava/net/URLStreamHandler; +20 -1: Detect premature EOF +94 -1: (Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)Lsun/nio/cs/StreamEncoder; +12 -1: NF_checkBase +20 -1: (Ljava/nio/Buffer;)V +45 -1: Ljava/util/Vector; +4 -1: Sync +12 -1: H_UNRESERVED +32 -1: (Ljava/util/Map;)Ljava/util/Set; +32 -1: (Ljava/util/Map$Entry;)Z +25 -1: java/util/Locale$Category +8 -1: receiver +9 -1: MAX_VALUE +4 -1: .RSA +25 -1: Ljava/net/URLClassLoader; +15 -1: Terminator.java +26 -1: (Ljava/lang/String;TV;)TV; +4 -1: null +76 -1: (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V +9 -1: checkCast +39 -1: ()Ljava/lang/AssertionStatusDirectives; +15 -1: declaredMethods +5 -1: clazz +21 -1: Retention policy: +20 -1: spreadArgElementType +9 -1: WORD_MASK +27 -1: ([IILjava/io/InputStream;)I +11 -1: getMethodAt +31 -1: (Ljava/net/URL;Ljava/net/URL;)Z +13 -1: getLocaleName +14 -1: isEnumConstant +41 -1: (Ljava/lang/String;)Ljava/nio/CharBuffer; +16 -1: newInvokeSpecial +26 -1: (Ljava/nio/ByteBuffer;IS)V +22 -1: sun/misc/JavaNioAccess +184 -1: (Ljava/security/DomainCombiner;Ljava/lang/Class;Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;[Ljava/security/Permission;)Ljava/security/AccessControlContext; +96 -1: (Ljava/lang/invoke/MethodHandle;ILjava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle; +5 -1: ([S)I +30 -1: java/security/AccessController +37 -1: sun/misc/Launcher$SharedArchiveLoader +4 -1: pack +5 -1: ([S)V +51 -1: failure before throwing exception, dump stack +10 -1: dayOfMonth +6 -1: CENSIG +28 -1: java/util/function/Predicate +26 -1: Malformed \\uxxxx encoding. +9 -1: initIndex +11 -1: invoke_LL_L +23 -1: ConcurrentWeakInternSet +14 -1: java/lang/Void +42 -1: java/lang/String$CaseInsensitiveComparator +38 -1: Ljava/lang/invoke/LambdaForm$Compiled; +34 -1: java/util/Collections$SingletonSet +142 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/invoke/CallSite; +35 -1: too many bootstrap method arguments +17 -1: maxDelimCodePoint +13 -1: previousIndex +3 -1: pop +6 -1: CENSIZ +7 -1: ([Z[Z)Z +11 -1: invoke_LL_V +3 -1: pos +33 -1: java/nio/file/WatchEvent$Modifier +3 -1: pow +12 -1: nextClearBit +15 -1: Dictionary.java +27 -1: sun/reflect/CallerSensitive +13 -1: signatureType +10 -1: dstSavings +13 -1: UnicodeLittle +16 -1: America/New_York +82 -1: (Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)Ljava/util/Locale; +25 -1: referenceKindIsConsistent +62 -1: Ljava/nio/Buffer;Ljava/lang/Comparable; +4 -1: INTS +11 -1: LOAD_FACTOR +40 -1: sun/reflect/DelegatingMethodAccessorImpl +16 -1: accumulateAndGet +21 -1: (B)Ljava/lang/String; +6 -1: UNSAFE +13 -1: resolveOrFail +21 -1: MapReduceMappingsTask +5 -1: arity +77 -1: (Ljava/io/FileDescriptor;ZZLjava/lang/Object;)Ljava/nio/channels/FileChannel; +5 -1: value +61 -1: Ljava/util/concurrent/ConcurrentHashMap$EntrySetView; +6 -1: forJar +52 -1: Ljava/lang/ref/Reference; +21 -1: CREATE_ACC_PERMISSION +28 -1: sun/misc/NativeSignalHandler +11 -1: defineClass +5 -1: match +93 -1: (Ljava/util/zip/ZipFile;Ljava/util/zip/ZipFile$ZipFileInputStream;Ljava/util/zip/Inflater;I)V +11 -1: Double.java +30 -1: America/Argentina/Buenos_Aires +8 -1: previous +37 -1: (Ljava/io/Writer;Ljava/lang/String;)V +9 -1: Synthetic +18 -1: isVMAnonymousClass +62 -1: ([Ljava/lang/Object;Ljava/lang/Object;Ljava/util/Comparator;)I +22 -1: (JI)Ljava/lang/String; +49 -1: (Ljava/lang/CharSequence;II)Ljava/io/PrintStream; +52 -1: ([Ljava/lang/Thread;)[[Ljava/lang/StackTraceElement; +12 -1: setDayOfWeek +11 -1: getManifest +30 -1: java/util/Locale$FilteringMode +54 -1: (Ljava/lang/String;)Lsun/util/calendar/CalendarSystem; +12 -1: nextHashCode +19 -1: ()Ljava/io/Console; +42 -1: AccessControlContext invoking the Combiner +19 -1: shouldBeInitialized +17 -1: invocationCounter +21 -1: IMPLEMENTATION_VENDOR +7 -1: chararr +60 -1: (Ljava/lang/String;)Ljava/util/Iterator; +11 -1: asCollector +52 -1: (ILjava/lang/CharSequence;)Ljava/lang/StringBuilder; +9 -1: exception +22 -1: newInstanceCallerCache +20 -1: nativeLibraryContext +24 -1: MODIFY_THREAD_PERMISSION +4 -1: WRAP +19 -1: Method name is null +32 -1: sun/invoke/util/ValueConversions +7 -1: APP_TAG +24 -1: (Ljava/util/Hashtable;)I +23 -1: METHOD_FORMAL_PARAMETER +18 -1: inflationThreshold +24 -1: java/io/DeleteOnExitHook +3 -1: pst +13 -1: BITS_PER_WORD +25 -1: getConstructorAnnotations +17 -1: CheckedCollection +24 -1: (Ljava/util/Hashtable;)V +7 -1: inClass +5 -1: getFD +8 -1: readLong +19 -1: aliases_ISO_8859_13 +19 -1: invokeWithArguments +19 -1: aliases_ISO_8859_15 +42 -1: ()Ljava/util/concurrent/ConcurrentHashMap; +8 -1: expandTo +23 -1: java/text/MessageFormat +8 -1: classID0 +11 -1: replaceWith +21 -1: Invalid port number : +65 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V +19 -1: isGregorianLeapYear +16 -1: asSpreaderChecks +11 -1: withInitial +10 -1: X-UTF-32BE +57 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +12 -1: wrong type: +57 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z +17 -1: sun/misc/Resource +14 -1: getReadTimeout +8 -1: safeTrim +38 -1: DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING +14 -1: isElementIndex +23 -1: FilterOutputStream.java +6 -1: (IJI)V +3 -1: put +57 -1: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String; +43 -1: Expecting an absolute path of the library: +8 -1: checkRef +53 -1: (Ljava/lang/String;)Ljava/lang/AbstractStringBuilder; +74 -1: (Ljava/lang/Class<*>;[Ljava/lang/reflect/Field;)[Ljava/lang/reflect/Field; +11 -1: user.script +10 -1: H_ALPHANUM +17 -1: getCalendarSystem +48 -1: Ljava/util/concurrent/ConcurrentHashMap; +17 -1: EnsureInitialized +82 -1: (Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal;Ljava/lang/Object;)V +243 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;Ljava/util/function/ToIntBiFunction;ILjava/util/function/IntBinaryOperator;)V +26 -1: getAnnotatedExceptionTypes +10 -1: validIndex +6 -1: ([CC)I +8 -1: overflow +5 -1: getID +93 -1: (Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)Lsun/nio/cs/StreamDecoder; +22 -1: java/util/StringJoiner +9 -1: putFields +18 -1: USE_SHARED_ARCHIVE +8 -1: thursday +8 -1: nanoTime +59 -1: (Lsun/reflect/annotation/AnnotationType;Ljava/lang/Class;)V +69 -1: (Ljava/nio/charset/CoderResult$Cache;I)Ljava/nio/charset/CoderResult; +36 -1: (J)Ljava/lang/AbstractStringBuilder; +16 -1: java/util/Arrays +6 -1: ([CC)V +25 -1: registerAsParallelCapable +4 -1: slot +24 -1: java/net/URLConnection$1 +6 -1: koi8-r +19 -1: should be of type +46 -1: java/util/concurrent/ConcurrentHashMap$TreeBin +6 -1: koi8-u +34 -1: data type scale not a power of two +53 -1: Ljava/util/Map; +21 -1: AccessibleObject.java +53 -1: ()Ljava/util/NavigableSet; +88 -1: (Ljava/util/List;Ljava/util/Collection;Ljava/util/Locale$FilteringMode;)Ljava/util/List; +17 -1: getAnnotationType +36 -1: Ljava/util/HashMap$TreeNode; +14 -1: declaringClass +10 -1: read,write +5 -1: getId +10 -1: BIG_ENDIAN +20 -1: PolymorphicSignature +16 -1: comparingByValue +67 -1: (ILjava/lang/invoke/MethodType;)[Ljava/lang/invoke/LambdaForm$Name; +19 -1: java/util/Hashtable +20 -1: getUnicodeLocaleKeys +27 -1: ()Ljava/util/LinkedHashMap; +51 -1: (Ljava/lang/CharSequence;)Ljava/lang/StringBuilder; +30 -1: java/util/HashMap$HashIterator +22 -1: (IZ)Ljava/lang/String; +5 -1: yield +34 -1: java/lang/Throwable$SentinelHolder +62 -1: (Ljava/lang/invoke/MethodType;ZI)Ljava/lang/invoke/LambdaForm; +5 -1: (FD)F +17 -1: java/util/SubList +24 -1: (Ljava/io/PrintStream;)V +7 -1: LF.zero +25 -1: java/util/StringTokenizer +15 -1: ISO8859_15_FDIS +11 -1: powerOfTwoD +11 -1: powerOfTwoF +22 -1: WeakHashMapSpliterator +15 -1: refKindIsGetter +12 -1: setRawOffset +11 -1: setProperty +23 -1: (Ljava/lang/Object;IB)V +45 -1: (ILjava/lang/Object;)Ljava/util/HashMap$Node; +13 -1: applyAsDouble +83 -1: (Lsun/misc/URLClassPath$FileLoader;Ljava/lang/String;Ljava/net/URL;Ljava/io/File;)V +19 -1: MethodAccessor.java +9 -1: WALL_TIME +7 -1: INVOKES +13 -1: java.ext.dirs +9 -1: getStatic +56 -1: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String; +42 -1: (Ljava/util/function/UnaryOperator;)V +27 -1: java/lang/Class$MethodArray +10 -1: H_USERINFO +19 -1: PostVMInitHook.java +7 -1: running +32 -1: Warning: passing argument as-is +13 -1: EntryIterator +22 -1: NF_checkSpreadArgument +46 -1: ([DLjava/util/function/IntToDoubleFunction;I)V +7 -1: . +13 -1: mappingLength +20 -1: implOnMalformedInput +53 -1: (Ljava/lang/String;ILjava/lang/reflect/Executable;I)V +26 -1: cannot make variable arity +18 -1: SharedSecrets.java +27 -1: (Ljava/io/InputStream;IZ)[B +9 -1: Asia/Gaza +55 -1: Ljava/util/Map;>; +5 -1: NTLM +19 -1: defaultCenturyStart +18 -1: addElapsedTimeFrom +38 -1: (Lsun/misc/Cleaner;)Lsun/misc/Cleaner; +44 -1: (Ljava/io/OutputStream;ZLjava/lang/String;)V +22 -1: (Ljava/lang/Object;B)V +6 1: [LBar; +7 -1: classes +23 -1: java/net/URLClassLoader +17 -1: sun/misc/Launcher +163 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)[Ljava/util/concurrent/ConcurrentHashMap$Node; +12 -1: updateAndGet +90 -1: (Ljava/net/URL;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V +9 -1: increment +27 -1: (Ljava/lang/CharSequence;)V +16 -1: Ljava/io/Reader; +27 -1: java/io/PushbackInputStream +6 -1: (JFZ)V +17 -1: getAppClassLoader +35 -1: sun/reflect/generics/tree/Signature +9 -1: elementAt +27 -1: (Ljava/lang/CharSequence;)Z +10 -1: readDouble +37 -1: ([B)Ljava/nio/charset/CharsetEncoder; +46 -1: (Ljava/lang/ThreadGroup;Ljava/lang/Runnable;)V +4 -1: park +36 -1: java/lang/NegativeArraySizeException +49 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Z +121 -1: ;>(Ljava/util/function/Function<-TT;+TU;>;)Ljava/util/Comparator; +101 -1: (Ljava/lang/annotation/Annotation;Ljava/lang/annotation/Annotation;)Ljava/lang/annotation/Annotation; +12 -1: .$|()[{^?*+\\ +6 -1: manRef +3 -1: 437 +15 -1: newStringUnsafe +15 -1: constantPoolOop +10 -1: getPackage +24 -1: FastCharsetProvider.java +18 -1: getAnnotationBytes +187 -1: (Ljava/security/DomainCombiner;Ljava/lang/Class<*>;Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;[Ljava/security/Permission;)Ljava/security/AccessControlContext; +33 -1: Cannot suppress a null exception. +27 -1: sun/nio/cs/StandardCharsets +33 -1: (BB)Ljava/lang/invoke/MemberName; +61 -1: ([Ljava/lang/ClassValue$Entry;ILjava/lang/ClassValue$Entry;)I +10 -1: X-UTF-32LE +5 -1: toMap +89 -1: (Ljava/lang/Class<*>;Ljava/util/List;>;)Ljava/lang/invoke/MethodType; +46 -1: ([Ljava/lang/Object;IILjava/util/Comparator;)V +66 -1: ([Ljava/lang/reflect/Constructor;)[Ljava/lang/reflect/Constructor; +22 -1: ()Ljava/nio/ByteOrder; +20 -1: isMethodHandleInvoke +25 -1: sun/net/www/URLConnection +89 -1: Ljava/util/concurrent/ConcurrentHashMap; +49 -1: (Ljava/nio/charset/Charset;FFLjava/lang/String;)V +17 -1: MIN_LOW_SURROGATE +23 -1: AbstractCollection.java +19 -1: (Ljava/util/Date;)I +19 -1: (Ljava/util/Date;)J +12 -1: cldrdata.jar +4 -1: path +77 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;IILjava/lang/String;[B)V +6 -1: MS1250 +37 -1: setJavaSecurityProtectionDomainAccess +11 -1: isDelimiter +5 -1: char0 +6 -1: MS1251 +5 -1: char1 +16 -1: getJavaNetAccess +6 -1: MS1252 +6 -1: MS1253 +6 -1: MS1254 +51 -1: (Ljava/lang/Class;)Ljava/security/ProtectionDomain; +6 -1: MS1257 +93 -1: (Ljava/lang/String;Ljava/nio/ByteBuffer;Ljava/security/ProtectionDomain;)Ljava/lang/Class<*>; +10 -1: access$300 +5 -1: (JZ)C +19 -1: (Ljava/util/Date;)Z +5 -1: (JZ)D +26 -1: java/lang/Character$Subset +10 -1: access$302 +5 -1: (JZ)F +9 -1: emptyList +5 -1: (JZ)I +5 -1: (JZ)J +23 -1: (Ljava/lang/Runnable;)V +27 -1: java/lang/invoke/MemberName +29 -1: ()Ljava/util/Comparator; +18 -1: retrieveDirectives +7 -1: ([F[F)Z +40 -1: (Lsun/misc/URLClassPath;Ljava/net/URL;)V +5 -1: (JZ)S +40 -1: (Ljava/util/function/IntUnaryOperator;)I +5 -1: (JZ)V +16 -1: parseAnnotations +21 -1: (C)Ljava/lang/String; +73 -1: (TK;TV;)Ljava/util/Map; +15 -1: charset encoder +17 -1: getDomainCombiner +9 -1: EmptyList +15 -1: java.vm.version +19 -1: getResourceAsStream +94 -1: Ljava/lang/ThreadLocal;>; +26 -1: java/util/HashMap$TreeNode +22 -1: (Ljava/util/HashMap;)V +23 -1: sun/misc/URLClassPath$1 +65 -1: ([Ljava/net/URL;Ljava/lang/ClassLoader;)Ljava/net/URLClassLoader; +20 -1: Hashtable Enumerator +23 -1: sun/misc/URLClassPath$2 +10 -1: Array.java +8 -1: FT_LIMIT +24 -1: ()[Ljava/lang/Throwable; +23 -1: sun/misc/URLClassPath$3 +14 -1: java/io/Writer +5 -1: chars +76 -1: ()Ljava/util/NavigableMap; +6 -1: final +5 -1: error +34 -1: java/lang/ApplicationShutdownHooks +29 -1: Lsun/launcher/LauncherHelper; +30 -1: ()Ljava/util/Enumeration; +47 -1: (Ljava/util/List;)Ljava/lang/invoke/MethodType; +9 -1: scriptKey +5 -1: BYTES +12 -1: getException +69 -1: (Ljava/lang/Class<*>;Ljava/lang/Object;)Ljava/lang/invoke/MethodType; +14 -1: Illegal Load: +189 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;Ljava/util/function/BiFunction;)V +66 -1: java/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask +29 -1: getJavaIOFileDescriptorAccess +11 -1: toCodePoint +15 -1: setCreationTime +18 -1: NULL_CAUSE_MESSAGE +8 -1: elements +32 -1: ()Ljava/nio/charset/CoderResult; +8 -1: utf-32be +7 -1: addDate +4 -1: Cast +23 -1: sun/misc/JavaLangAccess +8 -1: 0{1,12}$ +27 -1: (Ljava/util/ArrayList;III)V +11 -1: lastIndexOf +14 -1: getCodeSources +53 -1: (Lsun/util/calendar/CalendarDate;Ljava/lang/String;)V +17 -1: cachedConstructor +7 -1: forName +74 -1: (Ljava/util/function/ToLongFunction;Ljava/lang/Object;Ljava/lang/Object;)I +47 -1: (Ljava/lang/Object;)Lsun/reflect/FieldAccessor; +8 -1: getDebug +18 -1: currentClassLoader +49 -1: Illegal leading minus sign on unsigned string %s. +20 -1: toLowerCaseCharArray +38 -1: java/util/concurrent/ConcurrentHashMap +8 -1: isHidden +92 -1: (Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;)V +29 -1: java/lang/ArithmeticException +26 -1: (Ljava/io/OutputStream;Z)V +66 -1: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/RuntimeException; +38 -1: Ljava/util/Map; +16 -1: getFindClassTime +34 -1: ([J)Ljava/util/Spliterator$OfLong; +24 -1: UnmodifiableNavigableSet +32 -1: java/lang/ClassNotFoundException +3 -1: \\n +6 -1: SEALED +14 -1: Flushable.java +3 -1: HST +24 -1: (Ljava/lang/Object;JII)Z +13 -1: toSecondOfDay +16 -1: thenComparingInt +26 -1: java/lang/NoSuchFieldError +18 -1: java/util/Locale$1 +25 -1: [Ljava/util/HashMap$Node; +75 -1: ([Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +11 -1: x-mswin-936 +32 -1: java/lang/management/MemoryUsage +25 -1: (JS)Ljava/nio/ByteBuffer; +25 -1: java/lang/ref/Finalizer$1 +25 -1: java/lang/ref/Finalizer$2 +21 -1: (Ljava/util/BitSet;)V +25 -1: java/lang/ref/Finalizer$3 +83 -1: (Ljava/util/Collection<+TT;>;Ljava/util/Comparator<-TT;>;)TT; +24 -1: sun/nio/ch/Interruptible +21 -1: (Ljava/util/BitSet;)Z +72 -1: ([Ljava/security/ProtectionDomain;Ljava/security/AccessControlContext;)V +54 -1: Ljava/util/AbstractSet;>; +34 -1: getConstructorParameterAnnotations +4 -1: name +92 -1: ;>Ljava/lang/Object;Ljava/lang/Comparable;Ljava/io/Serializable; +11 -1: FORM_OFFSET +13 -1: getAliasTable +5 -1: (DD)D +23 -1: reflectionFactoryAccess +221 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;Ljava/util/function/Function;Ljava/util/function/BiFunction;)V +59 -1: (Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path; +6 -1: DELETE +10 -1: returnType +5 -1: (DD)I +51 -1: ()Lsun/reflect/generics/repository/FieldRepository; +8 -1: delegate +12 -1: OTHER_LETTER +18 -1: getTransitionIndex +3 -1: HUP +10 -1: (IIII[CI)V +10 -1: ISO_8859-1 +17 -1: ArrayEncoder.java +10 -1: ISO_8859-2 +34 -1: java/lang/reflect/AnnotatedElement +10 -1: ISO_8859-4 +27 -1: sun/nio/cs/UTF_16LE$Decoder +10 -1: ISO_8859-5 +13 -1: prefetchWrite +9 -1: getFloatB +10 -1: ISO_8859-7 +37 -1: (I)Ljava/lang/invoke/LambdaForm$Name; +10 -1: ISO_8859-9 +10 -1: getActions +11 -1: negateExact +10 -1: isAbstract +9 -1: getFloatL +29 -1: java/lang/ClassValue$Identity +14 -1: java/io/Reader +8 -1: getOwner +24 -1: java/lang/AssertionError +17 -1: MethodHandle.java +19 -1: classRedefinedCount +10 -1: cachedYear +15 -1: getAndIncrement +26 -1: java.protocol.handler.pkgs +14 -1: cleanSomeSlots +27 -1: java/util/Spliterator$OfInt +31 -1: getRawExecutableTypeAnnotations +20 -1: ensureInitialization +7 -1: os.arch +57 -1: (Ljava/security/cert/CertPath;Ljava/security/Timestamp;)V +21 -1: UNSAFE_COPY_THRESHOLD +20 -1: toUnsignedBigInteger +82 -1: (Ljava/util/concurrent/locks/Condition;)Ljava/util/Collection; +15 -1: Reflection.java +12 -1: decryptBlock +3 -1: \\r +8 -1: newArray +8 -1: Category +36 -1: java/lang/reflect/GenericDeclaration +22 -1: (Ljava/lang/String;Z)V +8 -1: suspend0 +10 -1: getSigners +22 -1: (Ljava/lang/String;Z)Z +31 -1: Unable to create temporary file +117 -1: (Ljava/lang/ClassValue;Ljava/lang/ClassValue$Entry;)Ljava/lang/ClassValue$Entry; +17 -1: channelsAvailable +9 -1: Date.java +13 -1: toIndex < 0: +18 -1: mark > position: ( +11 -1: loadConvert +4 -1: july +42 -1: (Ljava/math/BigInteger;)Ljava/lang/String; +6 -1: enable +47 -1: (Ljava/util/zip/ZipEntry;)Ljava/io/InputStream; +6 -1: unpack +13 -1: setDayOfMonth +19 -1: name can't be empty +16 -1: getExtensionKeys +15 -1: getAndDecrement +36 -1: Ljava/lang/ClassValue$ClassValueMap; +38 -1: (Ljava/lang/Class;Ljava/lang/String;)V +11 -1: csISOlatin0 +9 -1: retention +23 -1: system protocol handler +9 -1: nullsLast +15 -1: refKindIsStatic +3 -1: (\n +48 -1: sun/launcher/LauncherHelper$ResourceBundleHolder +29 -1: ()Ljava/util/LinkedList; +11 -1: csISOlatin9 +31 -1: ([CII)Ljava/lang/StringBuilder; +29 -1: (II)Ljava/lang/StringBuilder; +7 -1: pdcache +4 -1: june +12 -1: ;/?:@&=+$,[] +141 -1: ([Ljava/lang/invoke/LambdaForm$Name;[Ljava/lang/invoke/LambdaForm$Name;Ljava/lang/invoke/LambdaForm$Name;)[Ljava/lang/invoke/LambdaForm$Name; +32 -1: ()[Ljava/util/WeakHashMap$Entry; +110 -1: (Ljava/lang/Class<*>;ILjava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; +81 -1: (Lsun/reflect/annotation/AnnotationType;Lsun/reflect/annotation/AnnotationType;)Z +46 -1: String value %s exceeds range of unsigned int. +6 -1: close0 +6 -1: (JDZ)V +160 -1: Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/reflect/GenericDeclaration;Ljava/lang/reflect/Type;Ljava/lang/reflect/AnnotatedElement; +12 -1: LinkedValues +24 -1: java/nio/HeapCharBufferR +23 -1: jvmVersionInfoAvailable +16 -1: classLoaderDepth +33 -1: (Lsun/nio/ch/DirectBuffer;IIIII)V +32 -1: java/nio/file/attribute/FileTime +50 -1: java/util/concurrent/ConcurrentHashMap$CounterCell +73 -1: (Lsun/misc/URLClassPath$JarLoader;Lsun/misc/JarIndex;)Lsun/misc/JarIndex; +60 -1: (Ljava/net/URL;Ljava/lang/String;)Ljava/security/CodeSource; +25 -1: Ljava/lang/ref/Finalizer; +12 -1: utf-32be-bom +40 -1: (Ljava/lang/String;ILjava/lang/Object;)V +9 -1: THROW_UCS +23 -1: java/util/AbstractMap$1 +23 -1: java/util/AbstractMap$2 +10 -1: x-utf-32be +4 -1: (S)B +60 -1: (Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/LambdaForm; +20 -1: ResourceBundleHolder +4 -1: (S)I +13 -1: getSuppressed +17 -1: jdk_micro_version +4 -1: (S)J +9 -1: isNumeric +10 -1: variantKey +8 -1: utf-32le +47 -1: java/util/concurrent/ConcurrentHashMap$MapEntry +25 -1: ()Ljava/lang/Class<-TT;>; +6 -1: closed +4 -1: (S)S +15 -1: setStandardTime +10 -1: ShortCache +4 -1: (S)V +40 -1: sun/net/www/MessageHeader$HeaderIterator +17 -1: jdk_major_version +8 -1: FXHelper +6 -1: CENTIM +19 -1: java/security/Guard +46 -1: java.lang.invoke.MethodHandle.DUMP_CLASS_FILES +4 -1: ENUM +27 -1: Ljava/lang/SecurityManager; +39 -1: ([Ljava/lang/Class;[Ljava/lang/Class;)Z +11 -1: getFieldAt0 +12 -1: user.variant +28 -1: (Ljava/io/DataInputStream;)V +44 -1: ([JLjava/util/function/LongBinaryOperator;)V +7 -1: getRoot +3 -1: + +16 -1: identityHashCode +25 -1: java/security/Permissions +16 -1: Ljava/net/Proxy; +23 -1: java/io/ExpiringCache$1 +5 -1: more +10 -1: formatList +49 -1: (Ljava/lang/String;)Lsun/launcher/LauncherHelper; +29 -1: Relative path in absolute URI +11 -1: checkMapped +8 -1: Checksum +8 -1: " Radix: +9 -1: getAndAdd +9 -1: implReady +16 -1: SynchronizedList +30 -1: [Ljava/lang/StackTraceElement; +5 -1: right +13 -1: UTF_16BE.java +4 -1: HEAD +11 -1: isInvocable +6 -1: ENDCOM +15 -1: getPropertiesEx +6 -1: Unsafe +7 -1: IBM-819 +37 -1: : 0 <= i2 && i2 < names.length: 0 <= +19 -1: filterAndAddHeaders +22 -1: nativeParkEventPointer +18 -1: checkPositionIndex +13 -1: invalid url: +25 -1: out of range from input +9 -1: loadClass +12 -1: encodingName +9 -1: x-JIS0208 +38 -1: (Ljava/lang/Class;Ljava/lang/Object;)Z +28 -1: (I)Ljava/lang/reflect/Field; +17 -1: getJvmVersionInfo +6 -1: LIJFDV +21 -1: (D)Ljava/lang/String; +7 -1: oomeMsg +30 -1: java/io/InvalidObjectException +25 -1: java/io/FilterInputStream +32 -1: Ljava/net/ContentHandlerFactory; +13 -1: toUnsignedInt +17 -1: reconstitutionPut +37 -1: (Ljava/lang/Object;)Ljava/lang/Class; +14 -1: getContentType +43 -1: java/util/Collections$SynchronizedSortedSet +24 -1: (II)Ljava/nio/file/Path; +25 -1: JAVAFX_APPLICATION_MARKER +29 -1: (IC)Ljava/lang/StringBuilder; +13 -1: java/util/Set +10 -1: clearError +64 -1: (Ljava/lang/invoke/MethodType;[I)Ljava/lang/invoke/MethodHandle; +25 -1: java/io/FileInputStream$1 +8 -1: getFirst +36 -1: (Lsun/reflect/ConstructorAccessor;)V +84 -1: (Ljava/util/NavigableMap;Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/NavigableMap; +42 -1: (Ljava/lang/CharSequence;)Ljava/io/Writer; +52 -1: ([Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +6 -1: (IFI)V +62 -1: Ljava/lang/Object;Ljava/util/Queue; +17 -1: getHeaderFieldInt +16 -1: CheckedSortedMap +39 -1: (ZILjava/lang/String;)Ljava/lang/Class; +10 -1: getterName +10 -1: Asia/Tokyo +4 -1: Node +7 -1: rotate1 +13 -1: Stream closed +7 -1: rotate2 +9 -1: checkExec +17 -1: NF_checkExactType +18 -1: ReverseComparator2 +18 -1: arrayElementGetter +97 -1: (Ljava/util/ArrayPrefixHelpers$DoubleCumulateTask;Ljava/util/function/DoubleBinaryOperator;[DII)V +9 -1: iso8859-1 +9 -1: iso8859-2 +9 -1: iso8859-4 +9 -1: iso8859-5 +9 -1: iso8859-7 +16 -1: getPermissions +9 -1: iso8859-9 +9 -1: fromClass +17 -1: with modifiers " +8 -1: isBooted +24 -1: getCommonPoolParallelism +10 -1: initialize +47 -1: (TT;)Ljava/util/Set; +17 -1: checkElementIndex +14 -1: openConnection +47 -1: (Ljava/lang/Thread;Lsun/nio/ch/Interruptible;)V +12 -1: isAuthorized +17 -1: ReduceEntriesTask +7 -1: command +24 -1: ArithmeticException.java +24 -1: ensureOpenOrZipException +67 -1: (Lsun/util/calendar/CalendarDate;I)Lsun/util/calendar/CalendarDate; +39 -1: Ljava/lang/invoke/MethodHandles$Lookup; +31 -1: Enclosing constructor not found +34 -1: ()Lsun/util/calendar/BaseCalendar; +25 -1: (JLjava/lang/Object;JJJ)V +12 -1: > toIndex: +22 -1: LocaleObjectCache.java +19 -1: sun/misc/Launcher$1 +31 -1: java/util/HashMap$EntryIterator +8 -1: contains +60 -1: Ljava/lang/Object; +53 -1: (I[Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +19 -1: java/io/PrintStream +42 -1: java/lang/Math$RandomNumberGeneratorHolder +100 -1: (I)Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +14 -1: getCapturedArg +14 -1: getCodeSigners +20 -1: mark() not supported +56 -1: (Lsun/misc/URLClassPath;I)Lsun/misc/URLClassPath$Loader; +20 -1: java/lang/StrictMath +14 -1: annotationType +3 -1: IET +4 -1: lang +13 -1: JarEntry.java +9 -1: ([CIIII)I +9 -1: canEncode +5 -1: extra +30 -1: java/lang/ref/ReferenceQueue$1 +37 -1: java/nio/channels/ReadableByteChannel +73 -1: (Ljava/util/Map$Entry;)Z +24 -1: java/io/BufferedReader$1 +10 -1: x-utf-32le +16 -1: methodDescriptor +25 -1: (IJ)Ljava/nio/ByteBuffer; +18 -1: getSystemResources +46 -1: (Ljava/lang/String;I)Ljava/util/regex/Pattern; +46 -1: (Ljava/net/URL;)Lsun/misc/URLClassPath$Loader; +20 -1: calendars.properties +25 -1: implOnUnmappableCharacter +12 -1: signers_name +40 -1: (ZILjava/util/Locale;)Ljava/lang/String; +8 -1: (TE;)TE; +50 -1: ()Lsun/util/locale/provider/LocaleProviderAdapter; +11 -1: key is null +7 -1: encrypt +21 -1: millisUntilExpiration +55 -1: Unable to parse property sun.reflect.inflationThreshold +9 -1: checkExit +5 -1: SHORT +43 -1: java/util/Collections$UnmodifiableSortedSet +10 -1: ISO8859_15 +16 -1: verifyParameters +24 -1: buildAnnotatedInterfaces +15 -1: refKindIsSetter +45 -1: (JLjava/util/function/BiConsumer<-TK;-TV;>;)V +23 -1: (Ljava/lang/Object;IC)V +90 -1: (Ljava/lang/ClassValue$Entry;)Ljava/lang/ClassValue$Entry; +30 -1: (Ljava/net/URL;)Ljava/net/URI; +60 -1: (BLjava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Object;)V +43 -1: (Ljava/util/Collection;Ljava/lang/Object;)I +44 -1: (Ljava/net/URLConnection;)Ljava/lang/Object; +17 -1: Stream not marked +11 -1: targetCheck +127 -1: (Ljava/lang/Class<*>;ILjava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName; +11 -1: debugString +112 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Class;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle; +43 -1: (Ljava/util/Collection;Ljava/lang/Object;)V +15 -1: NF_staticOffset +22 -1: CASE_INSENSITIVE_ORDER +6 -1: unpark +29 -1: (Ljava/lang/CharSequence;II)I +59 -1: Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +19 -1: defaultFormatLocale +7 -1: combine +58 -1: (Ljava/util/Locale$LocaleKey;)Lsun/util/locale/BaseLocale; +29 -1: (Ljava/lang/CharSequence;II)V +35 -1: sun/util/calendar/BaseCalendar$Date +57 -1: Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater; +75 -1: ([Ljava/lang/reflect/Member;[Ljava/lang/String;)[Ljava/lang/reflect/Member; +15 -1: MethodType_init +5 -1: (JF)V +20 -1: AUTOSELECT_FILTERING +12 -1: invokeStatic +18 -1: readFileDescriptor +22 -1: java/lang/Terminator$1 +72 -1: (Ljava/lang/Object;Ljava/util/function/UnaryOperator;)Ljava/lang/Object; +17 -1: EMPTY_STACK_TRACE +13 -1: isSamePackage +32 -1: ()Ljava/security/DomainCombiner; +10 -1: decodeLoop +30 -1: DIRECTIONALITY_EUROPEAN_NUMBER +112 -1: (Ljava/util/List;Ljava/util/Collection;)Ljava/lang/String; +33 -1: (Ljava/util/function/Predicate;)Z +35 -1: logincontext login context results +17 -1: sun/nio/cs/UTF_16 +13 -1: SingletonList +5 -1: end= +7 -1: getURLs +17 -1: traceInstructions +22 -1: generateCustomizedCode +9 -1: NO_CHANGE +11 -1: Number.java +49 -1: (ITT;)Ljava/util/List; +19 -1: checkSpecifyHandler +8 -1: setValue +30 -1: (Ljava/net/URL;)Ljava/net/URL; +22 -1: (Ljava/lang/Object;C)V +19 -1: Negative capacity: +24 -1: ArrayStoreException.java +52 -1: (Ljava/lang/StringBuffer;II)Ljava/lang/StringBuffer; +14 -1: linkMethodImpl +42 -1: java/util/InvalidPropertiesFormatException +4 -1: last +19 -1: getLocalizedMessage +65 -1: (Ljava/text/MessageFormat;[Ljava/lang/String;)[Ljava/lang/String; +61 -1: Ljava/lang/Object;Ljava/util/Enumeration; +40 -1: (I[CII)Ljava/lang/AbstractStringBuilder; +27 -1: java.launcher.opt.datamodel +29 -1: (Ljava/lang/reflect/Method;)V +19 -1: SPECIFICATION_TITLE +123 -1: (Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;ILjava/lang/Class;)Lsun/reflect/SerializationConstructorAccessorImpl; +32 -1: (I[CII)Ljava/lang/StringBuilder; +29 -1: (Ljava/lang/reflect/Method;)Z +23 -1: (Z[B)Ljava/lang/String; +27 -1: sun/nio/cs/Surrogate$Parser +32 -1: (Ljavax/security/auth/Subject;)Z +29 -1: ()Ljava/lang/invoke/Invokers; +7 -1: getPool +7 -1: textOut +12 -1: getEntryTime +14 -1: classModifiers +47 -1: (Ljava/util/Locale$Category;)Ljava/util/Locale; +32 -1: getInheritedAccessControlContext +4 -1: rcbt +37 -1: (Ljava/lang/Class<*>;Ljava/io/File;)Z +25 -1: AccessControlContext.java +22 -1: FileURLConnection.java +12 -1: NaturalOrder +34 -1: sun/util/calendar/CalendarSystem$1 +94 -1: ([Ljava/lang/reflect/Method;Ljava/lang/String;[Ljava/lang/Class<*>;)Ljava/lang/reflect/Method; +17 -1: No enum constant +7 -1: ([DII)V +8 -1: register +23 -1: FINAL_QUOTE_PUNCTUATION +27 -1: ACCESS_CLIPBOARD_PERMISSION +15 -1: verifyConstants +20 -1: (Ljava/io/Writer;I)V +45 -1: (Ljava/lang/String;)Ljava/lang/reflect/Field; +24 -1: linkMethodHandleConstant +43 -1: (Ljava/io/OutputStream;Ljava/lang/String;)V +125 -1: (Ljava/util/Comparator<-TV;>;)Ljava/util/Comparator;>; +14 -1: ALL_PERMISSION +12 -1: createObject +10 -1: CRC32.java +14 -1: reservedMemory +22 -1: ensureCapacityInternal +11 -1: FormatData_ +9 -1: maxMemory +27 -1: (I)Ljava/util/ListIterator; +8 -1: UTF-16BE +27 -1: AbstractSequentialList.java +10 -1: access$400 +16 -1: Locale settings: +10 -1: access$402 +12 -1: HashSet.java +24 -1: java/lang/Long$LongCache +30 -1: [Ljava/lang/reflect/Parameter; +11 -1: single_step +45 -1: (Ljava/lang/String;)Lsun/security/util/Debug; +97 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;)Ljava/lang/invoke/SimpleMethodHandle; +16 -1: indexOfBangSlash +7 -1: region= +26 -1: ([BII)Ljava/lang/Class<*>; +8 -1: bitCount +3 -1: INT +67 -1: ([TT;Ljava/util/function/IntFunction<+TT;>;)V +35 -1: newGetFloatIllegalArgumentException +11 -1: ([DII[DII)V +22 -1: makePreparedLambdaForm +3 -1: < +35 -1: sun/management/GarbageCollectorImpl +4 -1: (*)* +7 -1: getPort +18 -1: java/io/FileSystem +7 -1: getNode +38 -1: (Ljava/lang/Object;I)Ljava/lang/Class; +36 -1: $SwitchMap$java$util$Locale$Category +18 -1: securityCheckCache +5 -1: cdate +10 -1: childValue +19 -1: getMainClassFromJar +70 -1: ;>(Ljava/lang/Class;Ljava/lang/String;)TT; +20 -1: unsuspendSomeThreads +29 -1: sun.classloader.findClassTime +11 -1: plusSeconds +3 -1: = +4 -1: Lock +7 -1: regions +38 -1: ()Ljava/lang/reflect/Constructor; +25 -1: parseParameterAnnotations +20 -1: getSystemGMTOffsetID +33 -1: [Cc][Oo][Dd][Ee][Bb][Aa][Ss][Ee]= +37 -1: (Ljava/lang/String;I)Ljava/lang/Byte; +10 -1: permission +78 -1: (Ljava/lang/reflect/Constructor;)Lsun/reflect/generics/scope/ConstructorScope; +28 -1: (Lsun/misc/JavaLangAccess;)V +26 -1: GET_CLASSLOADER_PERMISSION +24 -1: (J)Ljava/nio/ByteBuffer; +20 -1: getUnresolvedActions +49 -1: (I[BIILsun/security/util/ManifestEntryVerifier;)V +5 -1: (ZJ)V +14 -1: isClassOnlyJar +35 -1: ()[Ljava/util/HashMap$Node; +23 -1: ()Ljava/util/SortedMap; +29 -1: HistoricallyNamedCharset.java +30 -1: no leading reference parameter +8 -1: csCESU-8 +3 -1: > +13 -1: invoke_LLLL_L +109 -1: (Ljava/util/NavigableMap;)Ljava/util/NavigableMap; +13 -1: invoke_LLLL_V +46 -1: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Field; +5 -1: offer +12 -1: isoLanguages +61 -1: (Ljava/io/OutputStream;Ljava/lang/String;Ljava/lang/String;)V +44 -1: sun/reflect/BootstrapConstructorAccessorImpl +12 -1: BaseIterator +58 -1: (IZ[Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/String; +23 -1: initializeOSEnvironment +62 -1: ([Ljava/security/cert/Certificate;)[Ljava/security/CodeSigner; +3 -1: >> +13 -1: searchEntries +7 -1: setDate +3 -1: red +3 -1: ref +10 -1: EMPTY_LIST +3 -1: rem +78 -1: Ljava/util/AbstractCollection;Ljava/util/List; +9 -1: scanToken +6 -1: greek8 +9 -1: basicType +12 -1: getFromClass +43 -1: averageCharsPerByte exceeds maxCharsPerByte +8 -1: isDaemon +7 -1: nonNull +17 -1: Invalid default: +45 -1: (Lsun/misc/URLClassPath;Ljava/lang/String;Z)V +18 -1: java/lang/String$1 +11 -1: copyMethods +15 -1: sun/misc/Signal +5 -1: float +18 -1: StreamDecoder.java +19 -1: no such constructor +14 -1: bad arity for +14 -1: divideUnsigned +10 -1: CODING_END +3 -1: IST +14 -1: HeaderIterator +9 -1: september +20 -1: makeVarargsCollector +6 -1: L_PATH +45 -1: (Ljava/lang/String;)Ljava/io/File$PathStatus; +24 -1: URI scheme is not "file" +85 -1: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class<*>;)V +27 -1: java/util/function/Supplier +17 -1: checkedCollection +8 -1: MapEntry +81 -1: (Ljava/lang/invoke/MethodHandle;ILjava/util/List;)Ljava/lang/invoke/MethodHandle; +34 -1: java/security/ProtectionDomain$Key +14 -1: List length = +39 -1: ([Ljava/lang/Object;)Ljava/lang/String; +87 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; +7 -1: unparse +28 -1: jarFileHasClassPathAttribute +40 -1: (Lsun/misc/JavaIOFileDescriptorAccess;)V +30 -1: (Ljava/lang/reflect/Field;ZZ)V +22 -1: GetPropertyAction.java +8 -1: RUNNABLE +10 -1: exprString +13 -1: getAnnotation +19 -1: class can't be null +22 -1: defaultAssertionStatus +8 -1: getName0 +16 -1: quoteReplacement +15 -1: getMemberVMInfo +42 -1: (Ljava/lang/Class<*>;)Ljava/lang/Class<*>; +16 -1: cachedLambdaForm +16 -1: addFinalRefCount +12 -1: getMethodAt0 +8 -1: ([ZII)[Z +44 -1: (Ljava/lang/Object;TV;Ljava/lang/Object;)TV; +4 -1: [TT; +29 -1: Ljava/lang/invoke/LambdaForm; +28 -1: java/util/DualPivotQuicksort +61 -1: ()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +17 -1: registerDirectory +8 -1: jarFiles +69 -1: (Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)Ljava/lang/String; +54 -1: [Ljava/util/concurrent/ConcurrentHashMap$Node; +15 -1: getDefaultValue +39 -1: sun/util/calendar/ZoneInfoFile$Checksum +20 -1: DISABLE_JAR_CHECKING +12 -1: CONTENT_TYPE +46 -1: array type not assignable to trailing argument +60 -1: ([TT;II)Ljava/util/stream/Stream; +47 -1: java.lang.invoke.MethodHandle.COMPILE_THRESHOLD +9 -1: toInstant +152 -1: (Ljava/util/NavigableMap;Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/NavigableMap; +7 -1: L_ALPHA +29 -1: java/lang/AbstractMethodError +29 -1: java/util/jar/Attributes$Name +15 -1: LOCALE_SETTINGS +19 -1: (J)Ljava/lang/Long; +4 -1: jar: +17 -1: ensureInitialized +13 -1: LAST_MODIFIED +40 -1: ([Ljava/lang/String;)[Ljava/lang/String; +7 -1: shuffle +70 -1: (Lsun/util/locale/LanguageTag;)Lsun/util/locale/InternalLocaleBuilder; +19 -1: isPackageAccessible +17 -1: compileToBytecode +11 -1: getPackages +237 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;Ljava/util/function/ToIntFunction;ILjava/util/function/IntBinaryOperator;)V +53 -1: java/util/concurrent/ConcurrentHashMap$KeySpliterator +26 -1: setURLStreamHandlerFactory +47 -1: access print all checkPermission results +22 -1: sun/reflect/MethodInfo +75 -1: (Ljava/lang/String;ZLjava/util/Set;)Lsun/misc/Resource; +6 -1: KOI8-R +14 -1: Character.java +5 -1: (SS)I +8 -1: unshared +73 -1: (Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class; +19 -1: replacementTreeNode +10 -1: BA_REGULAR +8 -1: UTF-16LE +44 -1: (Ljava/lang/Class<*>;[Ljava/lang/Class<*>;)V +22 -1: InputStreamReader.java +17 -1: getInvocationType +23 -1: getDeclaredConstructors +48 -1: [Lsun/reflect/generics/tree/FormalTypeParameter; +67 -1: (Ljava/util/Comparator;Ljava/util/Map$Entry;Ljava/util/Map$Entry;)I +6 -1: koi8_r +14 -1: ofTotalSeconds +16 -1: content-encoding +6 -1: koi8_u +10 -1: getEncoded +6 -1: ()[TT; +43 -1: ([ILjava/util/function/IntUnaryOperator;I)V +18 -1: getSecurityContext +13 -1: LF_GEN_LINKER +78 -1: (BLjava/lang/invoke/MemberName;Ljava/lang/Class;)Ljava/lang/invoke/MemberName; +49 -1: (Ljava/util/HashMap;[Ljava/util/HashMap$Node;II)V +19 -1: LinkedEntryIterator +23 -1: Warning: JIT compiler " +7 -1: static +100 -1: (Ljava/lang/Class;ZLjava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/util/List; +79 -1: (Ljava/util/Collection<+TT;>;)Ljava/util/Collection; +10 -1: iso-ir-100 +10 -1: iso-ir-101 +13 -1: toUpperString +31 -1: ()Ljava/util/Spliterator$OfInt; +43 -1: Ljava/lang/StringIndexOutOfBoundsException; +19 -1: Lsun/misc/JarIndex; +7 -1: Version +90 -1: (Ljava/lang/String;Ljava/nio/ByteBuffer;Ljava/security/ProtectionDomain;)Ljava/lang/Class; +10 -1: getHandler +45 -1: (ILjava/lang/Object;)Ljava/lang/StringBuffer; +28 -1: getDeclaredAnnotationsByType +46 -1: ([Ljava/lang/Class;Ljava/lang/StringBuilder;)V +53 -1: ()Ljava/util/Enumeration; +15 -1: addAllNonStatic +10 -1: iso-ir-110 +14 -1: Using VM: +17 -1: casReflectionData +26 -1: (Lsun/util/PreHashedMap;)I +24 -1: removeByNameAndSignature +4 -1: OS X +85 -1: (Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Z +16 -1: JarEntryIterator +38 -1: Ljava/lang/Class; +37 -1: Ljava/lang/Class; +28 -1: ([Ljava/util/HashMap$Node;)V +34 -1: java/lang/reflect/GenericArrayType +14 -1: annotationData +26 -1: (Lsun/util/PreHashedMap;)V +22 -1: checkPackageDefinition +30 -1: ACCUMULATED_DAYS_IN_MONTH_LEAP +12 -1: lowestOneBit +64 -1: (Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal;)V +16 -1: asReadOnlyBuffer +11 -1: getRealName +17 -1: StringCoding.java +10 -1: iso-ir-126 +11 -1: isSurrogate +8 -1: setError +138 -1: (Ljava/util/function/Function<-TT;+TU;>;Ljava/util/Comparator<-TU;>;)Ljava/util/Comparator; +8 -1: (TK;)TK; +4 -1: java +136 -1: (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;)TT; +36 -1: ()Lsun/util/locale/LocaleExtensions; +12 -1: doubleStream +28 -1: ()Ljava/util/SimpleTimeZone; +7 -1: :@&=+$, +94 -1: Ljava/lang/ThreadLocal;>; +64 -1: (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method; +19 -1: getSystemTimeZoneID +18 -1: ReentrantLock.java +8 -1: emptyMap +16 -1: getSavedProperty +249 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;Ljava/util/function/ToDoubleFunction;DLjava/util/function/DoubleBinaryOperator;)V +14 -1: KeySpliterator +13 -1: findResources +14 -1: forWrapperType +8 -1: floorMod +12 -1: isoCountries +10 -1: CheckedSet +21 -1: AbstractCalendar.java +12 -1: IS_INVOCABLE +45 -1: (Ljava/lang/Class;)Lsun/reflect/ConstantPool; +19 -1: checkSecurityAccess +13 -1: Invalid index +28 -1: STACK_TRACE_ELEMENT_SENTINEL +88 -1: (ILjava/lang/Object;Ljava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode; +130 -1: (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V +14 -1: aliases_IBM437 +10 -1: iso-ir-144 +10 -1: iso-ir-148 +35 -1: ()Ljava/nio/charset/CharsetDecoder; +95 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle; +16 -1: UnmodifiableList +40 -1: ()Ljava/util/concurrent/locks/Condition; +9 -1: Path.java +80 -1: ([BLsun/reflect/ConstantPool;Ljava/lang/Class;[Ljava/lang/Class;)Ljava/util/Map; +36 -1: Ljava/lang/Class; +124 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;)Ljava/lang/Object; +20 -1: privateGetParameters +24 -1: sun/nio/cs/StreamDecoder +12 -1: getFreeSpace +8 -1: US-ASCII +22 -1: negativeZeroDoubleBits +9 -1: putObject +13 -1: linkToVirtual +35 -1: Ljava/lang/Class; +15 -1: detectedCharset +26 -1: java/lang/reflect/Modifier +22 -1: JAVAFX_LAUNCH_MODE_JAR +32 -1: java/net/URLStreamHandlerFactory +7 -1: IBM-923 +80 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/String; +13 -1: TRANSFERINDEX +34 -1: (Lsun/nio/cs/StandardCharsets$1;)V +23 -1: ()Ljava/io/InputStream; +16 -1: ()Ljava/io/File; +41 -1: (Ljava/lang/String;)Ljava/nio/ByteBuffer; +22 -1: sun/reflect/Reflection +23 -1: java/lang/AutoCloseable +25 -1: BootstrapMethodError.java +19 -1: EnclosingMethodInfo +13 -1: transferIndex +18 -1: java/lang/Compiler +4 -1: zero +29 -1: java/util/Arrays$NaturalOrder +9 -1: language= +37 -1: Ljava/util/ArrayList; +73 -1: ()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject; +16 -1: balanceInsertion +82 -1: (Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V +11 -1: asIntBuffer +27 -1: (Ljava/util/LinkedList;II)V +13 -1: ofEpochSecond +19 -1: sunjce_provider.jar +21 -1: (F)Ljava/lang/String; +32 -1: >> does not contain binding << +21 -1: declaredPublicMethods +5 -1: FIELD +17 -1: getPrimitiveClass +127 -1: (Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;Ljava/lang/Class;Ljava/lang/String;)V +21 -1: replaceParameterTypes +73 -1: Ljava/util/Map;Ljava/security/PermissionCollection;>; +21 -1: (Ljava/lang/Double;)I +5 -1: floor +4 -1: halt +14 -1: newConstructor +48 -1: (Ljava/util/function/BiFunction<-TK;-TV;+TV;>;)V +17 -1: packageAccessLock +15 -1: America/Phoenix +19 -1: Incoming arguments: +11 -1: V_Monotonic +14 -1: decrementExact +15 -1: updatePositions +14 -1: toLocaleString +12 -1: appendEscape +7 -1: DISPLAY +27 -1: sun/nio/cs/US_ASCII$Decoder +13 -1: LITTLE_ENDIAN +6 -1: isNull +13 -1: TempDirectory +6 -1: LM_JAR +39 -1: JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +10 -1: isCompiled +36 -1: (Ljava/lang/AbstractStringBuilder;)Z +3 -1: run +17 -1: START_PUNCTUATION +33 -1: Ljava/util/Stack; +49 -1: (Ljava/lang/String;)Ljava/lang/invoke/LambdaForm; +28 -1: java/security/DomainCombiner +53 -1: (Ljava/lang/String;Ljava/util/Map;)Ljava/time/ZoneId; +81 -1: ([BLsun/reflect/ConstantPool;Ljava/lang/Class;)[Ljava/lang/reflect/AnnotatedType; +43 -1: java/lang/management/GarbageCollectorMXBean +11 -1: toTitleCase +12 -1: getHoldCount +4 -1: ()[B +4 -1: ()[C +4 -1: ()[J +20 -1: (Ljava/io/File;IZZ)Z +18 -1: fileTimeToUnixTime +23 -1: java/nio/HeapCharBuffer +30 -1: Ljava/lang/ref/ReferenceQueue; +6 -1: rt.jar +69 -1: (Ljava/util/function/ToIntFunction<-TT;>;)Ljava/util/Comparator; +21 -1: java/lang/ThreadLocal +25 -1: Ljava/lang/reflect/Field; +44 -1: (Ljava/lang/String;Ljava/lang/Throwable;ZZ)V +93 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/MethodHandle; +22 -1: getDayOfWeekDateBefore +37 -1: [Lsun/reflect/generics/tree/TypeTree; +83 -1: (Ljava/util/Map;)Ljava/util/Set; +10 -1: readFields +42 -1: (Ljava/net/URL;)Ljava/security/CodeSource; +44 -1: (Ljava/lang/String;IIJ)Ljava/nio/ByteBuffer; +27 -1: Ljava/util/Collection; +13 -1: checkResource +7 -1: rename0 +51 -1: (C)Ljava/lang/invoke/BoundMethodHandle$SpeciesData; +47 -1: sun/reflect/generics/repository/FieldRepository +11 -1: readBoolean +134 -1: (ILjava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)V +13 -1: getZoneOffset +17 -1: getJdkVersionInfo +21 -1: sun/misc/MessageUtils +23 -1: defaultAllowArraySyntax +31 -1: java/util/concurrent/locks/Lock +24 -1: java/lang/reflect/Method +7 -1: toUpper +17 -1: sun/misc/Signal$1 +51 -1: (JLjava/util/function/BiFunction<-TK;-TK;+TK;>;)TK; +28 -1: (Ljava/lang/ref/Reference;)Z +8 -1: nthreads +26 -1: MapReduceEntriesToLongTask +27 -1: (Ljava/util/NavigableSet;)V +10 -1: savedProps +25 -1: Lsun/security/util/Debug; +12 -1: CR_MALFORMED +13 -1: com.sun.proxy +17 -1: CharSequence.java +24 -1: (ILjava/lang/String;II)Z +13 -1: findNextValue +108 -1: ;V:Ljava/lang/Object;>()Ljava/util/Comparator;>; +5 -1: (FF)F +9 -1: typeClass +5 -1: (FF)I +11 -1: segmentMask +7 -1: (JJJJ)V +14 -1: aliases_CESU_8 +85 -1: (Ljava/lang/Class;Ljava/lang/invoke/MemberName;)Ljava/lang/invoke/DirectMethodHandle; +15 -1: getCalendarDate +21 -1: getDeclaredAnnotation +8 -1: ([BIIB)I +15 -1: stripExtensions +14 -1: getISO3Country +5 -1: short +47 -1: String value %s exceeds range of unsigned long. +34 -1: ()Ljava/security/ProtectionDomain; +8 -1: ([BIIB)V +23 -1: (Ljava/lang/Object;ID)V +47 -1: (Ljava/lang/String;Ljava/nio/charset/Charset;)V +29 -1: RuntimeVisibleTypeAnnotations +24 -1: (Ljava/io/InputStream;)V +39 -1: (Ljava/lang/Class;Ljava/lang/String;Z)V +16 -1: convertPrimitive +8 -1: (TK;)TV; +24 -1: (Ljava/io/InputStream;)Z +6 -1: start +243 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;Ljava/util/function/ToLongFunction;JLjava/util/function/LongBinaryOperator;)V +9 -1: asSpecial +20 -1: java/text/Normalizer +17 -1: DAYS_0000_TO_1970 +9 -1: toCharset +20 -1: REPLACEALL_THRESHOLD +20 -1: sun/net/util/URLUtil +16 -1: findLoadedClass0 +14 -1: localedata.jar +6 -1: Parser +6 -1: start0 +4 -1: hash +83 -1: (Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType; +29 -1: Ljava/lang/invoke/MemberName; +8 -1: BOOT_TAG +22 -1: MH_LINKER_ARG_APPENDED +14 -1: comparingByKey +47 -1: ([Ljava/lang/String;)Ljava/lang/ProcessBuilder; +6 -1: start= +18 -1: StringBuilder.java +7 -1: getLong +12 -1: copyElements +16 -1: highResFrequency +11 -1: toGMTString +10 -1: ISO_8859_1 +10 -1: ISO_8859_2 +6 -1: result +10 -1: ISO_8859_4 +10 -1: ISO_8859_5 +10 -1: ISO_8859_7 +15 -1: unmodifiableSet +10 -1: ISO_8859_9 +25 -1: NoClassDefFoundError.java +42 -1: (Ljava/lang/String;)Ljava/util/LinkedList; +14 -1: parallelPrefix +22 -1: ARRAY_LONG_INDEX_SCALE +6 -1: resume +36 -1: Ljava/lang/invoke/LambdaForm$Hidden; +50 -1: java/util/Collections$UnmodifiableRandomAccessList +130 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Consumer;)V +6 -1: getInt +13 -1: getCachedYear +21 -1: CONNECTOR_PUNCTUATION +73 -1: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;ILjava/lang/Class;)V +24 -1: [Lsun/util/calendar/Era; +22 -1: (Ljava/lang/Object;D)V +74 -1: (Ljava/security/AccessControlContext;)Ljava/security/AccessControlContext; +109 -1: (Ljava/lang/Class<*>;Ljava/lang/Class$AnnotationData;Ljava/lang/Class$AnnotationData;)Z +6 -1: ([CZ)V +74 -1: (Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node; +19 -1: TRADITIONAL_CHINESE +125 -1: (Ljava/lang/Throwable$PrintStreamOrWriter;[Ljava/lang/StackTraceElement;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V +18 -1: unknown protocol: +57 -1: (Ljava/lang/reflect/Method;Lsun/reflect/MethodAccessor;)V +13 -1: writeComments +9 -1: Negotiate +14 -1: Closeable.java +10 -1: asSpreader +122 -1: (Ljava/nio/file/WatchService;[Ljava/nio/file/WatchEvent$Kind;[Ljava/nio/file/WatchEvent$Modifier;)Ljava/nio/file/WatchKey; +17 -1: jvm_minor_version +9 -1: getDouble +25 -1: Ljava/io/File$PathStatus; +19 -1: averageCharsPerByte +22 -1: getConstructorAccessor +61 -1: (Ljava/lang/String;)Ljava/lang/management/MemoryManagerMBean; +45 -1: (Ljava/lang/String;)Ljava/util/regex/Pattern; +25 -1: (JC)Ljava/nio/ByteBuffer; +20 -1: exclusiveOwnerThread +85 -1: (Ljava/lang/ClassValue;Ljava/lang/ClassValue$Entry;)V +17 -1: getExtensionValue +14 -1: getLoadAverage +17 -1: GET_PD_PERMISSION +6 -1: METHOD +23 -1: sun/nio/cs/ISO_8859_1$1 +23 -1: (I[Ljava/lang/Object;)I +4 1: zzz1 +13 -1: createWrapper +4 1: zzz2 +4 1: zzz3 +33 -1: greater than Character.MAX_RADIX +37 -1: DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE +6 -1: BRIDGE +20 -1: canonicalizeLanguage +13 -1: setPermission +46 -1: (Ljava/io/OutputStream;)Ljava/io/OutputStream; +3 -1: 646 +14 -1: java/lang/Long +55 -1: java/util/concurrent/ConcurrentHashMap$SearchValuesTask +38 -1: (IC)Ljava/lang/invoke/LambdaForm$Name; +37 -1: (Ljava/lang/Class;)Ljava/lang/String; +17 -1: javaUtilJarAccess +23 -1: registerMethodsToFilter +34 -1: (Ljava/nio/charset/Charset;[CII)[B +11 -1: % VERSION 2 +37 -1: ([DI)Ljava/util/Spliterator$OfDouble; +16 -1: Stack Size: +52 -1: (Ljava/lang/Class;)Ljava/lang/annotation/Annotation; +17 -1: putDoubleVolatile +10 -1: access$500 +10 -1: access$502 +28 -1: malformed input around byte +13 -1: LF_INVSPECIAL +32 -1: Non-positive averageCharsPerByte +14 -1: NF_fieldOffset +10 -1: access$508 +48 -1: (TT;)Ljava/util/List; +17 -1: defaultReadObject +17 -1: java/util/TimSort +13 -1: resolveClass0 +92 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;[Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +20 -1: setLangReflectAccess +30 -1: java/lang/reflect/TypeVariable +56 -1: ([TT;)Ljava/util/Spliterator; +8 -1: VOLATILE +10 -1: Big5-HKSCS +23 -1: (Ljava/util/Locale$1;)V +15 -1: ISO_8859-1:1987 +14 -1: no such method +10 -1: null value +8 -1: checkURL +22 -1: ARRAY_BYTE_INDEX_SCALE +27 -1: (Ljava/lang/ClassLoader;Z)V +22 -1: java/lang/reflect/Type +25 -1: java/net/JarURLConnection +36 -1: java/util/WeakHashMap$KeySpliterator +26 -1: ()Lsun/misc/JavaAWTAccess; +50 -1: (I[Ljava/lang/Class;)Ljava/lang/invoke/MethodType; +9 -1: toDegrees +12 -1: lowSurrogate +19 -1: getEnclosingMethod0 +7 -1: bytearr +35 -1: (Ljava/util/List;Ljava/util/List;)I +25 -1: [Ljava/lang/reflect/Type; +34 -1: javaSecurityProtectionDomainAccess +21 -1: java.launcher.X.usage +37 -1: sun/util/locale/InternalLocaleBuilder +33 -1: ()Ljava/lang/invoke/MethodHandle; +3 -1: scl +19 -1: synthesizeAllParams +68 -1: Ljava/util/Map; +6 -1: vclass +35 -1: (Ljava/util/List;Ljava/util/List;)V +59 -1: Ljava/lang/Number;Ljava/lang/Comparable; +13 -1: CallSite.java +10 1: Bar loaded +21 -1: ARRAY_INT_BASE_OFFSET +49 -1: Ljava/util/concurrent/ConcurrentHashMap$TreeNode; +32 -1: [Ljava/lang/reflect/Constructor; +4 -1: type +34 -1: ([TT;II)[TT; +25 -1: BufferedOutputStream.java +23 -1: java/util/zip/ZipFile$1 +24 -1: ()Ljava/lang/ClassValue; +50 -1: (Ljava/util/concurrent/CountedCompleter;[F[FIIII)V +16 -1: getQueuedThreads +26 -1: getJavaNetHttpCookieAccess +8 -1: setExtra +8 -1: implRead +20 -1: linkMethod => throw +76 -1: (Ljava/util/function/ToDoubleFunction;Ljava/lang/Object;Ljava/lang/Object;)I +11 -1: KeyIterator +39 -1: Ljava/util/List; +3 -1: " " +36 -1: Ljava/lang/IllegalArgumentException; +11 -1: checkBounds +30 -1: sun/nio/cs/FastCharsetProvider +11 -1: toLongArray +107 -1: (Ljava/lang/Class<*>;Ljava/lang/String;Ljava/lang/Class<*>;IILjava/lang/String;[B)Ljava/lang/reflect/Field; +8 -1: (build +39 -1: (Ljava/nio/Buffer;ILjava/nio/Buffer;I)V +31 -1: [Ljava/lang/reflect/Executable; +3 -1: set +21 -1: PhantomReference.java +41 -1: java/util/Collections$CheckedNavigableMap +53 -1: Can not make a java.lang.Class constructor accessible +12 -1: ([CII[CIII)I +55 -1: Ljava/util/HashMap; +12 -1: MICROSECONDS +11 -1: writeBuffer +52 -1: and domain that didn't have permission +37 -1: java/nio/channels/WritableByteChannel +26 -1: getRawClassTypeAnnotations +15 -1: putCharVolatile +33 -1: java/security/InvalidKeyException +19 -1: Ljava/io/Closeable; +83 -1: Lsun/util/locale/LocaleObjectCache; +10 -1: SetFromMap +24 -1: JavaFX-Application-Class +13 -1: asShortBuffer +10 -1: getReifier +15 -1: isPositionIndex +18 -1: SignalHandler.java +3 -1: JST +28 -1: (Ljava/io/FileDescriptor;I)I +28 -1: getStackAccessControlContext +16 -1: updateByteBuffer +27 -1: ()Ljava/net/ContentHandler; +25 -1: (JD)Ljava/nio/ByteBuffer; +39 -1: ()Lsun/misc/JavaIOFileDescriptorAccess; +107 -1: (Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry; +42 -1: sun/misc/PerfCounter$WindowsClientCounters +8 -1: addExact +28 -1: (Ljava/io/FileDescriptor;I)V +36 -1: ([Ljava/lang/String;)Ljava/util/Map; +21 -1: ()Ljava/lang/Process; +4 -1: UTF8 +5 -1: mkdir +10 -1: transient +3 -1: sgp +15 -1: balanceDeletion +161 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/net/URL;)Ljava/lang/Package; +15 -1: SynchronizedMap +40 -1: sun.misc.URLClassPath.disableJarChecking +92 -1: Ljava/util/AbstractSet;Ljava/util/Set;Ljava/io/Serializable; +17 -1: removeEldestEntry +35 -1: (I)Ljava/lang/Class$AnnotationData; +24 -1: Ljava/util/Locale$Cache; +13 -1: STANDARD_TIME +17 -1: sun/nio/cs/MS1252 +99 -1: ()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +23 -1: java/util/LinkedHashSet +9 -1: iso8859_1 +9 -1: iso8859_2 +9 -1: iso8859_4 +66 -1: (Ljava/lang/Class;)[TA; +9 -1: iso8859_5 +9 -1: iso8859_7 +9 -1: iso8859_9 +21 -1: Ljava/util/Formatter; +6 -1: isPath +21 -1: makeReferenceIdentity +24 -1: sun/net/ApplicationProxy +23 -1: ClassCastException.java +11 -1: MethodArray +12 -1: SingletonMap +41 -1: java/util/ArrayPrefixHelpers$CumulateTask +7 -1: seconds +20 -1: ClassRepository.java +14 -1: allocateMemory +24 -1: java.launcher.jar.error1 +24 -1: java.launcher.jar.error2 +24 -1: java.launcher.jar.error3 +45 -1: (Ljava/lang/String;Ljava/util/jar/Manifest;)Z +3 -1: sin +7 -1: (J[II)I +3 -1: Itr +18 -1: findBootstrapClass +10 -1: getElement +15 -1: ISO_8859-4:1988 +34 -1: newGetLongIllegalArgumentException +7 -1: pending +17 -1: isNotContinuation +6 -1: EXTSIG +13 -1: searchMethods +32 -1: Lsun/misc/JavaUtilZipFileAccess; +33 -1: ([Ljava/lang/reflect/Parameter;)V +31 -1: defaultUncaughtExceptionHandler +89 -1: (Ljava/nio/file/WatchService;[Ljava/nio/file/WatchEvent$Kind<*>;)Ljava/nio/file/WatchKey; +5 -1: ASCII +28 -1: ()Lsun/reflect/ConstantPool; +20 -1: isJavaIdentifierPart +6 -1: EXTSIZ +34 -1: Lsun/misc/JavaNetHttpCookieAccess; +34 -1: ClassLoader object not initialized +7 -1: CHECKED +16 -1: encodeBufferLoop +37 -1: (Ljava/time/Instant;)Ljava/util/Date; +24 -1: (Ljava/util/Map$Entry;)Z +50 -1: java/util/concurrent/ConcurrentHashMap$KeyIterator +31 -1: ()[Ljava/lang/ClassValue$Entry; +31 -1: java/lang/IllegalStateException +43 -1: (Ljava/lang/Appendable;Ljava/util/Locale;)V +6 -1: CENVEM +53 -1: Ljava/util/ArrayList; +17 -1: getHeaderFieldKey +71 -1: (Ljava/lang/CharSequence;Ljava/text/Normalizer$Form;)Ljava/lang/String; +6 -1: CENVER +17 -1: cleanStaleEntries +9 -1: linkFirst +57 -1: (Ljava/util/Comparator<-TT;>;)Ljava/util/Comparator; +8 -1: val$file +27 -1: Invalid parameter modifiers +6 -1: append +57 -1: ()Lsun/reflect/generics/repository/ConstructorRepository; +65 -1: java/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask +39 -1: (Ljava/lang/String;)Ljava/lang/Integer; +25 -1: lambda$parallelSetAll$191 +25 -1: lambda$parallelSetAll$192 +25 -1: lambda$parallelSetAll$193 +23 -1: INSERTIONSORT_THRESHOLD +17 -1: java/time/Instant +25 -1: lambda$parallelSetAll$194 +14 -1: dynamicInvoker +9 -1: iso646-us +8 -1: position +29 -1: java/nio/channels/FileChannel +27 -1: java/util/stream/Collectors +64 -1: (Ljava/lang/CharSequence;Ljava/lang/Iterable;)Ljava/lang/String; +10 -1: INDEX_NAME +15 -1: getCommentBytes +67 -1: (Ljava/io/FileOutputStream;Ljava/lang/String;)Ljava/io/PrintStream; +22 -1: privateGetPublicFields +32 -1: java/util/BitSet$1BitSetIterator +12 -1: PERF_MODE_RO +89 -1: ([Ljava/lang/ClassValue$Entry;ILjava/lang/ClassValue$Entry;Z)Ljava/lang/ClassValue$Entry; +30 -1: java/security/PrivilegedAction +18 -1: host can't be null +26 -1: package name can't be null +12 -1: PERF_MODE_RW +10 -1: isEnqueued +18 -1: argSlotToParameter +37 -1: (II)Ljava/lang/AbstractStringBuilder; +5 -1: tabAt +53 -1: (Ljava/lang/Object;)Ljava/lang/AbstractStringBuilder; +11 -1: PATH_OFFSET +18 -1: unicodebigunmarked +15 -1: ConditionObject +6 -1: KOREAN +13 -1: isNamePresent +24 -1: ()Ljava/lang/Class; +14 -1: isStandardTime +8 -1: ([IIII)I +9 -1: WeakEntry +12 -1: javaIOAccess +17 -1: key can't be null +129 -1: Ljava/lang/Object;Ljava/lang/Comparable;Ljava/lang/Iterable;Ljava/nio/file/Watchable; +8 -1: handler +8 -1: ([IIII)V +10 -1: atBugLevel +18 -1: makeGuardWithCatch +18 -1: currentLoadedClass +11 -1: getCodeBase +67 -1: (Ljava/util/List<+TT;>;)Ljava/util/List; +12 -1: JarFile.java +19 -1: (C)Ljava/io/Writer; +22 -1: createURLStreamHandler +23 -1: sun/nio/cs/ArrayDecoder +13 -1: setAccessible +18 -1: stripOffParameters +101 -1: ([Ljava/security/ProtectionDomain;[Ljava/security/ProtectionDomain;)[Ljava/security/ProtectionDomain; +18 -1: Ljava/util/Random; +16 -1: Pacific/Honolulu +13 -1: useOldMapping +65 -1: (Ljava/lang/invoke/LambdaForm$NamedFunction;[Ljava/lang/Object;)V +14 -1: filterArgument +12 -1: LF_MH_LINKER +25 -1: isDirectMemoryPageAligned +49 -1: (Ljava/util/BitSet;)Ljava/util/function/Supplier; +54 -1: (Ljava/util/concurrent/ConcurrentHashMap;TV;)V +16 -1: java/time/ZoneId +4 -1: zfot +18 -1: isSameClassPackage +6 -1: julian +8 -1: (TT;)TT; +22 -1: java/util/jar/Manifest +7 -1: charOut +16 -1: getOffsetsByWall +19 -1: Illegal replacement +139 -1: Ljava/util/AbstractList;Ljava/util/List;Ljava/util/RandomAccess;Ljava/lang/Cloneable;Ljava/io/Serializable; +96 -1: (Ljava/lang/reflect/Constructor;)Ljava/lang/reflect/Constructor; +15 -1: Annotation.java +24 -1: (Ljava/lang/Class<*>;)[B +6 -1: CODING +34 -1: ([Ljava/lang/ClassValue$Entry;II)V +6 -1: IGNORE +62 -1: (Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; +29 -1: specificToGenericStringHeader +12 -1: helpTransfer +8 -1: fastTime +62 -1: (Ljava/net/URLConnection;[Ljava/lang/Class;)Ljava/lang/Object; +18 -1: Unhandled signal: +8 -1: isStrict +15 -1: ISO_8859-7:1987 +13 -1: getWeekLength +14 -1: jvmBuildNumber +40 -1: (Ljava/lang/String;)Ljava/util/Iterator; +6 -1: short0 +6 -1: short1 +73 -1: (Ljava/security/PrivilegedExceptionAction;)TT; +10 -1: removeNode +8 -1: setFloat +18 -1: cspc862latinhebrew +11 -1: setTimeZone +34 -1: java/lang/reflect/AccessibleObject +25 -1: MapReduceKeysToDoubleTask +25 -1: java/lang/ref/Reference$1 +24 -1: java/nio/HeapByteBufferR +15 -1: jdkMicroVersion +117 -1: (Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;IILjava/lang/String;[B[B[B)V +8 -1: (TT;)TV; +16 -1: Permissions.java +22 -1: Ljava/util/Comparator; +17 -1: getDaylightSaving +25 -1: ([BIILjava/lang/String;)V +9 -1: stillborn +11 -1: maxPosition +28 -1: java/util/ArrayPrefixHelpers +73 -1: ()Ljava/util/SortedMap; +14 -1: useCanonCaches +5 -1: clean +16 -1: checkPermission2 +34 -1: sun.misc.launcher.useSharedArchive +13 -1: shutdownHooks +5 -1: clear +240 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;Ljava/util/function/ToLongFunction;JLjava/util/function/LongBinaryOperator;)V +67 -1: (JLjava/util/function/Function<-TV;+TU;>;)TU; +6 -1: cp1250 +6 -1: cp1251 +6 -1: cp1252 +13 -1: getZipMessage +6 -1: cp1253 +28 -1: (J)Ljava/lang/ref/Reference; +6 -1: cp1254 +54 -1: (ILjava/lang/String;)Ljava/lang/AbstractStringBuilder; +6 -1: cp1257 +10 -1: deepEquals +17 -1: WRITE_BUFFER_SIZE +13 -1: copyFromArray +40 -1: java/util/Collections$ReverseComparator2 +36 -1: sun/reflect/generics/visitor/Reifier +19 -1: averageBytesPerChar +13 -1: javaAWTAccess +6 -1: cp5346 +61 -1: Ljava/util/Map; +6 -1: cp5347 +6 -1: cp5348 +6 -1: cp5349 +5 -1: field +23 -1: ()Ljava/nio/LongBuffer; +103 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/WrongMethodTypeException; +37 -1: (I)Ljava/lang/Character$UnicodeBlock; +11 -1: offsetAfter +79 -1: Ljava/util/HashMap; +27 -1: invocationHandlerReturnType +17 -1: POSITIVE_INFINITY +11 -1: maybeRebind +3 -1: str +18 -1: setSecurityManager +9 -1: signature +18 -1: corrupted jar file +89 -1: Ljava/lang/Object;Ljava/util/Collection;Ljava/io/Serializable; +87 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +6 -1: CENATT +6 -1: cp5350 +12 -1: AF_GETSTATIC +38 -1: (TE;Ljava/util/LinkedList$Node;)V +8 -1: isLoaded +6 -1: CENATX +6 -1: cp5353 +18 -1: Africa/Addis_Ababa +35 -1: sun/usagetracker/UsageTrackerClient +11 -1: toUpperCase +22 -1: java/util/zip/Inflater +10 -1: iso_8859-1 +10 -1: iso_8859-2 +3 -1: sum +7 -1: x-Johab +10 -1: iso_8859-4 +10 -1: iso_8859-5 +85 -1: (Ljava/security/DomainCombiner;Ljava/lang/Class;)Ljava/security/AccessControlContext; +11 -1: activeCount +49 -1: (Ljava/lang/ClassLoader;Ljava/lang/ClassLoader;)Z +51 -1: (Ljava/util/List;Ljava/lang/Class;)Ljava/util/List; +10 -1: iso_8859-7 +19 -1: appendVmErgoMessage +10 -1: iso_8859-9 +14 -1: getClassLoader +6 -1: (CJJ)Z +15 -1: Lsun/misc/Perf; +7 -1: getTree +27 -1: Ljava/text/Normalizer$Form; +11 -1: ISO-2022-JP +69 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Object;)Ljava/lang/Object; +50 -1: java/lang/invoke/DirectMethodHandle$StaticAccessor +15 -1: fxLauncherClass +35 -1: (Ljava/net/URL;Ljava/lang/String;)V +16 -1: getAndAccumulate +35 -1: (Ljava/net/URL;Ljava/lang/String;)Z +32 -1: Non-positive averageBytesPerChar +35 -1: Ljava/lang/Class; +15 -1: CLASS_MODIFIERS +12 -1: checkedQueue +13 -1: enumConstants +10 -1: getFactory +95 -1: Ljava/util/concurrent/ConcurrentMap;>; +13 -1: Africa/Harare +57 -1: (JLjava/util/TimeZone;)Lsun/util/calendar/Gregorian$Date; +11 -1: ISO-2022-KR +19 -1: $assertionsDisabled +13 -1: PROXY_PACKAGE +17 -1: copyFromLongArray +81 -1: Ljava/util/LinkedHashMap$Entry; +11 -1: checkDelete +38 -1: sun/management/ManagementFactoryHelper +7 -1: UTC1900 +20 -1: getBootstrapResource +23 -1: ()Ljava/lang/Throwable; +16 -1: CALLER_SENSITIVE +26 -1: checkSystemClipboardAccess +32 -1: Can't set default locale to NULL +16 -1: fxLauncherMethod +4 -1: >= +8 -1: provider +9 -1: Finalizer +78 -1: (Ljava/io/FileDescriptor;ZZZLjava/lang/Object;)Ljava/nio/channels/FileChannel; +13 -1: emptyIterator +15 -1: getZipFileCount +21 -1: isJavaIdentifierStart +9 -1: connected +11 -1: (ITK;TV;I)V +16 -1: America/Honolulu +22 -1: SynchronizedCollection +28 -1: java/util/zip/ZipConstants64 +29 -1: inheritedAccessControlContext +29 -1: ()[Ljava/security/CodeSigner; +85 -1: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/sun/management/GcInfo;)V +25 -1: (Ljava/nio/CharBuffer;Z)V +15 -1: java/io/Console +101 -1: (Ljava/lang/Class<*>;Lsun/reflect/annotation/AnnotationType;Lsun/reflect/annotation/AnnotationType;)Z +9 -1: | resolve +81 -1: (BLjava/lang/invoke/MemberName;Ljava/lang/Class<*>;)Ljava/lang/invoke/MemberName; +33 -1: (Ljava/nio/charset/Charset;FF[B)V +49 -1: (Ljava/lang/Class;Z)Ljava/lang/invoke/MethodType; +66 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)Ljava/io/File; +29 -1: ([Ljava/util/HashMap$Node;I)V +13 -1: filterMethods +4 -1: jcal +61 -1: (Ljava/util/List;>;)[Ljava/lang/Class<*>; +6 -1: which= +46 -1: (Ljava/math/BigInteger;)Ljava/math/BigInteger; +4 -1: date +18 -1: internalMemberName +6 -1: (JJI)Z +30 -1: [Ljava/lang/invoke/LambdaForm; +60 -1: Ljava/lang/Object; +15 -1: ReservationNode +42 -1: java/lang/ThreadLocal$ThreadLocalMap$Entry +6 -1: setIn0 +4 -1: sort +8 -1: ibm00858 +110 -1: (Ljava/lang/String;Ljava/nio/ByteBuffer;IILjava/security/ProtectionDomain;Ljava/lang/String;)Ljava/lang/Class; +28 -1: Ljava/lang/ClassValue$Entry; +22 -1: ensureExplicitCapacity +6 -1: rotate +14 -1: closeRequested +30 -1: ([CII)Ljava/lang/StringBuffer; +10 -1: LM_UNKNOWN +15 -1: Comparable.java +13 -1: getByteBuffer +9 -1: getScheme +15 -1: done with meta! +17 -1: checkForTypeAlias +7 -1: getKeys +7 -1: SIG_DFL +30 -1: Ljava/nio/charset/CoderResult; +16 -1: returnTypesMatch +19 -1: getClassAccessFlags +18 -1: JavaNioAccess.java +9 -1: setDouble +23 -1: Ljava/util/zip/ZipFile; +83 -1: (JLjava/util/function/ToIntFunction<-TK;>;ILjava/util/function/IntBinaryOperator;)I +11 -1: ACCESS_READ +15 -1: nativeByteOrder +5 -1: hours +7 -1: toArray +7 -1: Encoder +12 -1: resolveClass +29 -1: (Ljava/io/FileDescriptor;JJ)V +14 -1: redefinedCount +8 -1: getTotal +11 -1: iso_8859-13 +11 -1: iso_8859-15 +9 -1: expected +18 -1: getDeclaredMethods +11 -1: elementData +6 -1: intern +10 -1: countryKey +6 -1: setInt +39 -1: Could not create extension class loader +24 -1: SELF_SUPPRESSION_MESSAGE +14 -1: argToSlotTable +42 -1: Ljava/util/HashMap; +5 -1: \t\n\r\x0c +4 -1: read +12 -1: Objects.java +7 -1: aliases +29 -1: sun/reflect/LangReflectAccess +6 -1: prefix +15 -1: superInterfaces +10 -1: getDoInput +30 -1: java/nio/CharBufferSpliterator +6 -1: KOI8_R +12 -1: Asia/Kolkata +6 -1: KOI8_U +6 -1: LOCSIG +15 -1: UA-Java-Version +92 -1: Ljava/util/HashMap;Ljava/util/Map; +14 -1: CertificateRep +17 -1: getSystemResource +85 -1: (JLjava/util/function/ToLongFunction<-TV;>;JLjava/util/function/LongBinaryOperator;)J +27 -1: java/lang/reflect/Parameter +5 -1: quote +8 -1: not MH: +46 -1: java/util/Collections$UnmodifiableCollection$1 +6 -1: putVal +6 -1: LOCSIZ +6 -1: Atomic +3 -1: 737 +38 -1: java/lang/UnsupportedClassVersionError +27 -1: ()Ljava/lang/StringBuilder; +41 -1: sun/net/www/protocol/jar/JarURLConnection +60 -1: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter; +59 -1: (TT;TT;Ljava/util/Comparator<-TT;>;)I +54 -1: java/util/concurrent/locks/AbstractOwnableSynchronizer +7 -1: getHost +36 -1: (F)Ljava/lang/AbstractStringBuilder; +69 -1: (Ljava/lang/Class;)Ljava/lang/Class<+TU;>; +4 -1: Form +103 -1: (Ljava/util/SortedMap;)Ljava/util/SortedMap; +6 -1: spread +8 -1: addHours +13 -1: contentEquals +47 -1: (Ljava/lang/String;Ljava/security/Permission;)V +12 -1: newCondition +23 -1: (Ljava/lang/Object;IZ)V +26 -1: (Ljava/util/LinkedList;I)V +13 -1: ConstantValue +18 -1: URLConnection.java +12 -1: Boolean.java +75 -1: ([Ljava/net/URL;Ljava/lang/ClassLoader;Ljava/net/URLStreamHandlerFactory;)V +21 -1: EMPTY_THROWABLE_ARRAY +153 -1: (Ljava/util/Map;[Ljava/lang/String;>;Ljava/lang/Class<*>;[Ljava/lang/String;)Ljava/util/Map;[Ljava/lang/String;>; +18 -1: getUnresolvedCerts +13 -1: Negative time +28 -1: java/util/WeakHashMap$KeySet +8 -1: slashify +16 -1: isOtherLowercase +17 -1: putObjectVolatile +5 -1: ERASE +12 -1: filterFields +40 -1: Ljava/lang/ReflectiveOperationException; +12 -1: VM settings: +57 -1: (ILjava/lang/Object;)Ljava/util/HashMap$TreeNode; +10 -1: access$600 +11 -1: ] return => +13 -1: user.timezone +23 -1: USER_AGENT_JAVA_VERSION +27 -1: (Ljava/util/HashMap$Node;)V +19 -1: filterNTLMResponses +28 -1: (Lsun/misc/VMNotification;)V +37 -1: ()[[Ljava/lang/annotation/Annotation; +45 -1: ()Lcom/sun/management/DiagnosticCommandMBean; +3 -1: tan +31 -1: getDirectlyAndIndirectlyPresent +7 -1: prepend +35 -1: (I)Lsun/util/calendar/CalendarDate; +8 -1: val$dirs +4 -1: test +28 -1: Non-positive maxCharsPerByte +83 -1: Ljava/lang/Object;Ljava/util/Map; +12 -1: JAVA_VERSION +24 -1: ([Ljava/lang/Thread;IZ)I +70 -1: (Ljava/lang/invoke/LambdaForm$Name;)Ljava/lang/invoke/LambdaForm$Name; +57 -1: ([TT;Ljava/util/Comparator<-TT;>;)V +42 -1: (Ljava/lang/Class<*>;[I)Ljava/lang/Object; +27 -1: java/lang/SecurityManager$1 +32 -1: java/security/SignatureException +27 -1: java/lang/SecurityManager$2 +4 -1: .jar +20 -1: parameterAnnotations +31 -1: DIRECTIONALITY_BOUNDARY_NEUTRAL +21 -1: hasClassPathAttribute +17 -1: checkParentAccess +35 -1: java/security/PermissionsEnumerator +6 -1: FORMAT +92 -1: (JLjava/util/function/Function;+TU;>;)TU; +3 -1: 775 +11 -1: PROBE_LIMIT +111 -1: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater; +11 -1: AF_PUTFIELD +22 -1: (Ljava/lang/Object;Z)V +20 -1: getGenericReturnType +9 -1: val$extcl +13 -1: inClassLoader +37 -1: sun.urlClassLoader.readClassBytesTime +35 -1: (JLjava/util/function/BiConsumer;)V +28 -1: getContentHandlerPkgPrefixes +10 -1: getChannel +78 -1: (Ljava/util/List<+TT;>;TT;Ljava/util/Comparator<-TT;>;)I +16 -1: parseMemberValue +4 -1: regn +47 -1: ([Ljava/lang/Object;III)Ljava/util/Spliterator; +11 -1: but found +6 -1: adjust +11 -1: isLowerCase +29 -1: sun/reflect/ReflectionFactory +98 -1: (Ljava/util/SortedSet;Ljava/lang/Class;)Ljava/util/SortedSet; +18 -1: [Ljava/lang/Error; +5 -1: entry +14 -1: refreshVersion +8 -1: (IIIII)V +22 -1: unmodifiableCollection +6 -1: putAll +22 -1: offsetByCodePointsImpl +26 -1: (Ljava/lang/String;[BII)[C +46 -1: (Ljava/net/URLClassLoader;Ljava/lang/String;)V +4 -1: /LF= +9 -1: Bits.java +30 -1: [Ljava/util/WeakHashMap$Entry; +19 -1: getLastModifiedTime +44 -1: [Ljava/lang/Thread$UncaughtExceptionHandler; +11 -1: getZoneInfo +6 -1: lookup +19 -1: MapReduceValuesTask +18 -1: isVarargsCollector +38 -1: java/util/jar/JarFile$JarEntryIterator +11 -1: getJarIndex +9 -1: getByName +42 -1: (Ljava/lang/Object;JLjava/lang/Object;JJ)V +71 -1: (Ljava/lang/invoke/LambdaForm$Name;I)Ljava/lang/invoke/LambdaForm$Name; +30 -1: java/net/ContentHandlerFactory +54 -1: (Ljava/lang/Class<*>;I)Ljava/lang/invoke/MethodHandle; +12 -1: getSignature +9 -1: parseLong +25 -1: DEBUG_METHOD_HANDLE_NAMES +15 -1: runFinalization +13 -1: 0000000000000 +28 -1: ()[Ljava/lang/reflect/Field; +37 -1: ([Ljava/lang/ClassValue$Entry<*>;II)V +13 -1: gcInfoBuilder +64 -1: (JLjava/util/function/BiFunction;Ljava/util/function/Consumer;)V +5 -1: cnfe1 +8 -1: setShort +28 -1: (C)Ljava/lang/StringBuilder; +44 -1: (Ljava/nio/LongBuffer;)Ljava/nio/LongBuffer; +70 -1: (Ljava/lang/String;[BIILjava/security/CodeSource;)Ljava/lang/Class<*>; +33 -1: java/lang/TypeNotPresentException +5 -1: \n +20 -1: acquireInterruptibly +21 -1: (I)Ljava/lang/String; +24 -1: (Ljava/io/PrintWriter;)V +16 -1: convertArguments +32 -1: Ljava/net/MalformedURLException; +15 -1: linkToInterface +39 -1: java/lang/Throwable$PrintStreamOrWriter +10 -1: iso8859_13 +13 -1: hasPrimitives +10 -1: iso8859_15 +145 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Class<*>;)Ljava/lang/invoke/CallSite; +8 -1: equalPDs +28 -1: (Ljava/io/FileDescriptor;J)V +7 -1: newLine +43 -1: (Ljava/lang/Class<*>;I)Ljava/lang/Class<*>; +8 -1: addEntry +30 -1: java/util/WeakHashMap$EntrySet +14 -1: USE_OLDMAPPING +39 -1: (Ljava/io/DataInput;)Ljava/lang/String; +12 -1: LF_EX_LINKER +27 -1: java/lang/invoke/MethodType +23 -1: JavaSecurityAccess.java +23 -1: isLocalOrAnonymousClass +19 -1: Expanded arguments: +18 -1: sun/nio/cs/Unicode +40 -1: ()Ljava/nio/charset/spi/CharsetProvider; +23 -1: ([BLjava/lang/String;)V +7 -1: default +13 -1: highestOneBit +9 -1: isDefault +28 -1: (IF)Ljava/lang/StringBuffer; +31 -1: ()Ljava/util/ListIterator; +4 -1: base +23 -1: newPermissionCollection +7 -1: version +15 -1: Permission.java +41 -1: java/lang/invoke/LambdaForm$NamedFunction +8 -1: isQueued +24 -1: ([Ljava/lang/Class<*>;)I +64 -1: java/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask +16 -1: checkInitialized +37 -1: java/lang/ClassLoader$ParallelLoaders +5 -1: ([B)I +23 -1: Lsun/misc/URLClassPath; +9 -1: usr_paths +10 -1: Queue.java +43 -1: (Ljava/io/File;Ljava/nio/charset/Charset;)V +64 -1: (Ljava/lang/invoke/MethodTypeForm;)Ljava/lang/invoke/MemberName; +3 -1: tid +23 -1: JarIndex-Version: 1.0\n\n +33 -1: (I)Ljava/nio/charset/CoderResult; +5 -1: ([B)V +10 -1: isInstance +25 -1: unmappableCharacterAction +11 -1: queueLength +5 -1: ([B)Z +10 -1: freeMemory +47 -1: java/util/ArrayPrefixHelpers$DoubleCumulateTask +52 -1: (Ljava/util/Map;Ljava/lang/Class;Ljava/lang/Class;)V +41 -1: Ljava/util/Collections$ReverseComparator; +16 -1: copyToShortArray +206 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)Z +38 -1: sun/launcher/LauncherHelper$SizePrefix +17 -1: ACCESS_PERMISSION +17 -1: ReverseComparator +30 -1: ()Ljava/lang/ClassValue$Entry; +17 -1: AF_PUTSTATIC_INIT +6 -1: (IIB)I +19 -1: java/nio/file/Files +35 -1: (Z)[Ljava/lang/reflect/Constructor; +20 -1: INVALID_FIELD_OFFSET +17 -1: initializeHeaders +10 -1: management +10 -1: targetType +61 -1: (Ljava/util/SortedSet;Ljava/lang/Class;)Ljava/util/SortedSet; +5 -1: ascii +8 -1: validate +78 -1: Ljava/util/concurrent/ConcurrentHashMap; +25 -1: sun/nio/cs/UTF_16$Decoder +36 -1: sun/management/DiagnosticCommandImpl +24 -1: unmodifiableNavigableMap +18 -1: canonicalizeScript +29 -1: Lsun/misc/JavaSecurityAccess; +74 -1: ([JLjava/util/function/IntToLongFunction;)Ljava/util/function/IntConsumer; +38 -1: DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING +11 -1: languageTag +33 -1: java/lang/invoke/VolatileCallSite +18 -1: setRequestProperty +6 -1: 0x%02X +20 -1: (Ljava/lang/Float;)I +35 -1: (Ljava/nio/charset/CoderResult$1;)V +24 -1: (Ljava/lang/Object;JJB)V +21 -1: synchronizedSortedSet +59 -1: (Ljava/util/function/ToLongFunction;)Ljava/util/Comparator; +30 -1: av.length == arity: av.length= +7 -1: $VALUES +27 -1: RandomNumberGeneratorHolder +3 -1: tlr +43 -1: java/util/ArraysParallelSortHelpers$FJFloat +28 -1: ()[Ljava/io/File$PathStatus; +26 -1: invalid extra field length +13 -1: getExtensions +7 -1: PARAMS0 +7 -1: PARAMS1 +30 -1: [Ljava/lang/invoke/MemberName; +7 -1: PARAMS2 +31 -1: java/lang/AbstractStringBuilder +161 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/BiFunction;Ljava/util/function/Consumer;)V +4 -1: repl +19 -1: ()Ljava/lang/Class; +24 -1: BufferedInputStream.java +9 -1: sizeCache +8 -1: READLINK +9 -1: metaIndex +18 -1: getLocalizedObject +6 -1: filter +58 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V +140 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName; +24 -1: Ljava/util/HashMap$Node; +35 -1: (Lsun/nio/cs/FastCharsetProvider;)V +8 -1: dispatch +19 -1: sun.stderr.encoding +130 -1: (Ljava/util/List;Ljava/util/Collection;)Ljava/util/List; +51 -1: Ljava/util/concurrent/ConcurrentHashMap$ValuesView; +30 -1: sun.reflect.inflationThreshold +20 -1: MutableCallSite.java +26 -1: invokeWithArgumentsTracing +7 -1: getters +38 -1: ()[Ljava/lang/reflect/TypeVariable<*>; +46 -1: ([DLjava/util/function/DoubleBinaryOperator;)V +5 -1: klass +13 -1: publicMethods +37 -1: ()[Ljava/lang/reflect/Constructor<*>; +126 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle; +6 -1: FJLong +20 -1: canBeStaticallyBound +17 -1: getTimezoneOffset +9 -1: ALL_TYPES +3 -1: toV +8 -1: packages +15 -1: codePointBefore +10 -1: getCountry +13 -1: getDSTSavings +100 -1: (Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/CharsetDecoder;)Lsun/nio/cs/StreamDecoder; +50 -1: java/util/ArraysParallelSortHelpers$FJFloat$Sorter +20 -1: hasNonVoidPrimitives +7 -1: syncAll +41 -1: domain dump all domains in context +59 -1: Ljava/util/Hashtable; +16 -1: ForEachEntryTask +18 -1: vminfoIsConsistent +26 -1: (ZLjava/util/Comparator;)V +9 -1: Lock.java +31 -1: Lsun/reflect/ReflectionFactory; +8 -1: (I[BII)I +23 -1: doesExtendFXApplication +87 -1: java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl +11 -1: windows-31j +28 -1: sun/misc/URLClassPath$Loader +17 -1: getEntryAfterMiss +47 -1: ([Ljava/lang/reflect/Field;Ljava/lang/String;)J +44 -1: Ljava/util/List; +10 -1: openStream +31 -1: Ljava/net/UnknownHostException; +19 -1: bad reference kind +29 -1: ()Ljava/nio/MappedByteBuffer; +9 -1: H_UPALPHA +37 -1: (Ljava/util/function/UnaryOperator;)V +25 -1: FAKE_METHOD_HANDLE_INVOKE +4 -1: peek +25 -1: java/util/Hashtable$Entry +18 -1: getMemberRefInfoAt +37 -1: Ljava/util/WeakHashMap$Entry; +14 -1: resolvedHandle +27 -1: ()Ljava/util/Iterator; +61 -1: Ljava/util/Map; +6 -1: static +50 -1: (Ljava/net/URLClassLoader;)Lsun/misc/URLClassPath; +38 -1: (Ljava/lang/Class;)[Ljava/lang/Object; +41 -1: (Ljava/util/SortedSet;Ljava/lang/Class;)V +41 -1: java/lang/invoke/WrongMethodTypeException +5 -1: group +10 -1: readObject +13 -1: getParentFile +14 -1: daylightSaving +15 -1: eagerValidation +36 -1: (Ljava/io/File;)Lsun/misc/MetaIndex; +18 -1: reduceEntriesToInt +15 -1: INITIAL_ENTRIES +18 -1: AtomicInteger.java +7 -1: .length +128 -1: Ljava/nio/Buffer;Ljava/lang/Comparable;Ljava/lang/Appendable;Ljava/lang/CharSequence;Ljava/lang/Readable; +6 -1: asList +21 -1: unmodifiableSortedSet +22 -1: ([B)Ljava/util/BitSet; +5 -1: check +64 -1: (Ljava/util/jar/JarFile;Lsun/misc/MetaIndex;)Lsun/misc/JarIndex; +35 -1: ()Ljava/nio/charset/CharsetEncoder; +4 -1: oome +25 -1: ()Lsun/misc/URLClassPath; +27 -1: (Ljava/io/FilePermission;)V +29 -1: IllegalArgumentException.java +17 -1: jvmSpecialVersion +21 -1: Ljava/util/ArrayList; +13 -1: packagePrefix +27 -1: (Ljava/io/FilePermission;)Z +11 -1: canonicalID +82 -1: Ljava/lang/Object;Ljava/util/Comparator;Ljava/io/Serializable; +24 -1: java.launcher.opt.footer +13 -1: NativeLibrary +37 -1: (Ljava/lang/String;J)Ljava/lang/Long; +16 -1: longBitsToDouble +6 -1: getKey +22 -1: (JLjava/lang/String;)V +14 -1: ensureCapacity +69 -1: (Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; +22 -1: java/lang/Thread$State +50 -1: ()Ljava/util/Iterator; +4 -1: 7bit +46 -1: (Ljava/lang/Class<+Ljava/lang/ClassLoader;>;)Z +76 -1: (ILjava/util/List;>;)[Ljava/lang/invoke/LambdaForm$Name; +3 -1: ttb +12 -1: UTF_16LE_BOM +9 -1: remainder +40 -1: ()Lsun/reflect/generics/visitor/Reifier; +22 -1: [Ljava/lang/Throwable; +17 -1: EMPTY_ENUMERATION +13 -1: erasedInvoker +46 -1: Ljava/nio/charset/IllegalCharsetNameException; +10 -1: UnicodeBig +53 -1: ()Ljava/util/Map; +12 -1: MAX_EXPONENT +10 -1: Enumerator +15 -1: charset decoder +11 -1: AF_GETFIELD +12 -1: | getInvoker +74 -1: (Ljava/nio/ByteBuffer;Ljava/nio/CharBuffer;)Ljava/nio/charset/CoderResult; +14 -1: toUnsignedLong +46 -1: java/lang/invoke/MethodHandleNatives$Constants +29 -1: java version "1.8.0-internal" +21 -1: ([Ljava/lang/Class;)I +16 -1: UPPERCASE_LETTER +22 -1: newConstantPerfCounter +6 -1: signum +9 -1: getField0 +38 -1: java/nio/charset/CoderMalfunctionError +21 -1: [Ljava/lang/Runnable; +11 -1: putIfAbsent +30 -1: java/util/Collections$EmptySet +22 -1: (I)[Ljava/lang/String; +34 -1: Ljava/security/SecurityPermission; +49 -1: ([Ljava/lang/Class;)Ljava/lang/invoke/MethodType; +190 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;Ljava/util/function/BiFunction;)V +22 -1: Not an annotation type +34 -1: java/io/ObjectInputStream$GetField +50 -1: (Lsun/reflect/FieldInfo;)Ljava/lang/reflect/Field; +32 -1: Ljava/lang/NoSuchFieldException; +70 -1: (Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object; +9 -1: mergeSort +77 -1: (ITK;TV;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode; +21 -1: sun/nio/cs/ISO_8859_1 +8 -1: DST_MASK +21 -1: Ljava/lang/Throwable; +108 -1: (Ljava/lang/ref/SoftReference;>;I)Ljava/lang/Class$ReflectionData; +32 -1: java/util/Arrays$LegacyMergeSort +59 -1: ()[Ljava/lang/reflect/TypeVariable;>; +16 -1: parseUnsignedInt +36 -1: ([D)Ljava/util/Spliterator$OfDouble; +26 -1: SPECIFY_HANDLER_PERMISSION +13 -1: primitiveType +17 -1: threadStartFailed +21 -1: (J)Ljava/lang/String; +23 -1: setClassAssertionStatus +28 -1: java/util/Hashtable$EntrySet +28 -1: Non-positive maxBytesPerChar +19 -1: getApplicationClass +14 -1: SentinelHolder +15 -1: staticFieldBase +25 -1: setDefaultRequestProperty +66 -1: java/util/concurrent/ConcurrentHashMap$ForEachTransformedValueTask +8 -1: threadID +9 -1: getFields +15 -1: LineNumberTable +38 -1: java/util/Collections$CheckedSortedSet +14 -1: jdkBuildNumber +6 -1: divide +46 -1: (Ljava/io/BufferedWriter;Ljava/lang/String;Z)V +20 -1: java/lang/Terminator +92 -1: (Lsun/misc/URLClassPath$JarLoader;Ljava/lang/String;Ljava/net/URL;Ljava/util/jar/JarEntry;)V +6 -1: force0 +10 -1: getThreads +34 -1: java/util/IllformedLocaleException +115 -1: (Ljava/lang/String;Lsun/reflect/generics/factory/GenericsFactory;)Lsun/reflect/generics/repository/FieldRepository; +9 -1: testFlags +11 -1: getLanguage +36 -1: java/util/function/IntBinaryOperator +12 -1: Suppressed: +10 -1: isMandated +23 -1: MethodAccessorImpl.java +28 -1: (Ljava/util/zip/ZipEntry;)[B +27 -1: Ljava/util/Hashtable$Entry; +5 -1: table +10 -1: Short.java +19 -1: ReferenceQueue.java +8 -1: setTabAt +26 -1: ()Lsun/invoke/empty/Empty; +53 -1: (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; +74 -1: (ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node; +19 -1: changeParameterType +61 -1: Ljava/util/Map; +23 -1: (Ljava/lang/Object;IF)V +32 -1: (I)Ljava/util/ListIterator; +6 -1: unread +12 -1: isSubclassOf +6 -1: (JJJ)V +3 -1: Key +105 -1: (Ljava/util/HashMap;[Ljava/util/HashMap$Node;ITK;TV;)Ljava/util/HashMap$TreeNode; +14 -1: x-utf-16le-bom +22 -1: ()Ljava/nio/IntBuffer; +104 -1: (Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; +21 -1: removeFirstOccurrence +21 -1: sun/misc/DoubleConsts +23 -1: ()Ljava/util/SortedSet; +11 -1: getManEntry +23 -1: URI is not hierarchical +7 -1: replace +16 -1: getDisplayScript +11 -1: ISO_8859-15 +16 -1: permuteArguments +5 -1: (JI)C +41 -1: Error decoding percent encoded characters +22 -1: ([I)Ljava/lang/String; +31 -1: java/lang/management/ThreadInfo +9 -1: useCaches +22 -1: withInternalMemberName +5 -1: (JI)I +5 -1: (JI)J +67 -1: Ljava/lang/Object;Ljava/util/Collection; +95 -1: (Ljava/util/jar/JarFile;[Ljava/security/CodeSource;)Ljava/util/Enumeration; +7 -1: release +56 -1: (Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String; +5 -1: (JI)V +46 -1: (Ljava/util/Iterator;I)Ljava/util/Spliterator; +18 -1: verifyMemberAccess +9 -1: warning: +23 -1: java/lang/reflect/Field +67 -1: (Ljava/lang/String;Lsun/reflect/generics/factory/GenericsFactory;)V +10 -1: SizePrefix +15 -1: setJavaIOAccess +6 -1: (JI)[B +10 -1: ST_FLUSHED +10 -1: resolution +9 -1: ST_CODING +16 -1: sun/misc/Cleaner +21 -1: (Ljava/lang/Class;)[B +18 -1: WeakReference.java +41 -1: (Ljava/util/List;Ljava/util/Comparator;)V +18 -1: printPropertyValue +3 -1: 813 +22 -1: setRunFinalizersOnExit +4 -1: init +44 -1: ()Ljava/util/Iterator; +3 -1: 819 +12 -1: listIterator +8 -1: , arity= +24 -1: (Ljava/util/ArrayList;)I +49 -1: (IJLjava/io/FileDescriptor;Ljava/lang/Runnable;)V +10 -1: principals +17 -1: x-ISO-2022-CN-CNS +22 -1: (Ljava/lang/Object;F)V +14 -1: setReadTimeout +19 -1: getProtectionDomain +13 -1: pathSeparator +12 -1: getAndSetInt +58 -1: (Ljava/util/List;Ljava/util/Collection;)Ljava/util/Locale; +11 -1: setWritable +4 -1: perf +50 -1: ()Ljava/util/concurrent/ConcurrentHashMap; +6 -1: LOCTIM +6 -1: status +11 -1: replaceName +52 -1: (Ljava/lang/CharSequence;II)Ljava/lang/StringBuffer; +9 -1: nextToken +13 -1: dropArguments +20 -1: RECOGNIZED_MODIFIERS +14 -1: getInputStream +9 -1: readFully +25 -1: (CLjava/nio/CharBuffer;)I +24 -1: sun/misc/PathPermissions +10 -1: malformedN +9 -1: n is null +19 -1: instanceof Double: +13 -1: markSupported +26 -1: fromMethodDescriptorString +43 -1: [Ljava/util/concurrent/locks/ReentrantLock; +17 -1: parseUnsignedLong +33 -1: Lsun/misc/URLClassPath$JarLoader; +26 -1: (Ljava/io/OutputStream;I)V +6 -1: L_DASH +17 -1: EmptyNavigableMap +19 -1: CharsetDecoder.java +18 -1: makeDynamicInvoker +12 -1: URLUtil.java +27 -1: ()Ljava/util/Iterator; +9 -1: initTable +11 -1: getFragment +7 -1: isLower +20 -1: getMethodOrFieldType +29 -1: java/util/function/BiFunction +10 -1: access$700 +3 -1: 850 +7 -1: UTC2037 +43 -1: java/util/ArraysParallelSortHelpers$FJShort +9 -1: toSTZTime +10 -1: access$702 +3 -1: 852 +8 -1: hashCode +3 -1: 855 +44 -1: (Ljava/lang/ThreadLocal;Ljava/lang/Object;)V +3 -1: 857 +3 -1: 858 +5 -1: erase +55 -1: ()Ljava/lang/Class<+Ljava/lang/annotation/Annotation;>; +47 -1: (Ljava/util/Iterator;JI)Ljava/util/Spliterator; +38 -1: Ljava/nio/charset/spi/CharsetProvider; +22 -1: can't deserialize enum +13 -1: LF_EX_INVOKER +18 -1: java/text/Collator +18 -1: Zero length string +49 -1: ()Ljava/util/Iterator; +5 -1: amd64 +12 -1: getNameCount +7 -1: inCheck +52 -1: (Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)V +53 -1: (ILjava/lang/CharSequence;II)Ljava/lang/StringBuffer; +21 -1: java/util/WeakHashMap +8 -1: throws +52 -1: (Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)Z +55 -1: Ljava/lang/ref/SoftReference; +16 -1: emptyEnumeration +3 -1: 862 +89 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;ILjava/lang/Class;)Ljava/util/List; +3 -1: 866 +55 -1: Lsun/reflect/generics/repository/ConstructorRepository; +35 -1: (Ljava/lang/ref/ReferenceQueue$1;)V +33 -1: java/util/Collections$CheckedList +18 -1: prefetchReadStatic +7 -1: (JI[I)I +78 -1: (Ljava/lang/ThreadLocal$ThreadLocalMap;)Ljava/lang/ThreadLocal$ThreadLocalMap; +7 -1: ordinal +22 -1: FilterInputStream.java +26 -1: java/util/zip/ZipConstants +28 -1: JVM cannot find invoker for +43 -1: sun/reflect/generics/parser/SignatureParser +51 -1: (Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)V +73 -1: (Ljava/util/function/ToIntFunction;Ljava/lang/Object;Ljava/lang/Object;)I +17 -1: StringBuffer.java +62 -1: ([Ljava/lang/Object;Ljava/lang/StringBuilder;Ljava/util/Set;)V +6 -1: equals +9 -1: formatter +3 -1: 874 +35 -1: newGetShortIllegalArgumentException +74 -1: (Ljava/nio/CharBuffer;Ljava/nio/ByteBuffer;)Ljava/nio/charset/CoderResult; +3 -1: ucp +60 -1: ([Ljava/lang/ClassValue$Entry;I)Ljava/lang/ClassValue$Entry; +6 -1: create +17 -1: makeReinvokerForm +18 -1: csisolatincyrillic +15 -1: incrementAndGet +24 -1: maybeInstantiateVerifier +33 -1: ()Ljava/nio/channels/FileChannel; +6 -1: class +16 -1: getAnnotatedType +43 -1: (Ljava/lang/reflect/Type;)Ljava/lang/Class; +9 -1: HASH_BITS +12 -1: placeInCache +38 -1: java/util/Collections$SynchronizedList +89 -1: (Ljava/net/URL;Ljava/util/jar/JarFile;Ljava/util/jar/JarEntry;)Ljava/security/CodeSource; +22 -1: (Ljava/lang/String;I)B +20 -1: Ljava/util/TimeZone; +16 -1: sun.java.command +28 -1: java/util/WeakHashMap$Values +10 -1: X-UTF-16BE +22 -1: (Ljava/lang/String;I)I +26 -1: java/nio/DirectCharBufferS +99 -1: (Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class<*>; +22 -1: (Ljava/lang/String;I)J +26 -1: java/nio/DirectCharBufferU +54 -1: (Ljava/util/function/Supplier;)Ljava/lang/ThreadLocal; +21 -1: java/util/AbstractSet +37 -1: (Ljava/lang/String;)Ljava/lang/Short; +36 -1: Ljava/nio/charset/CoderResult$Cache; +22 -1: (Ljava/lang/String;I)S +15 -1: Ljava/util/Map; +59 -1: (Ljava/lang/reflect/Type;)Ljava/lang/reflect/AnnotatedType; +22 -1: (Ljava/lang/String;I)V +10 -1: getAddress +25 -1: java/nio/DirectIntBufferS +11 -1: IMPL_LOOKUP +3 -1: uee +7 -1: addTime +37 -1: sun/security/action/GetPropertyAction +25 -1: java/nio/DirectIntBufferU +21 -1: javaUtilZipFileAccess +34 -1: java/util/Collections$CheckedQueue +11 -1: readResolve +22 -1: (Ljava/lang/String;I)Z +11 -1: findVirtual +63 -1: (Ljava/lang/String;Ljava/lang/String;)Lsun/security/util/Debug; +22 -1: getDeclaredAnnotations +16 -1: Collections.java +18 -1: invalid entry size +49 -1: java/util/concurrent/ConcurrentHashMap$TableStack +32 -1: java/util/AbstractSequentialList +4 -1: int0 +16 -1: MAXIMUM_CAPACITY +53 -1: ()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; +4 -1: int1 +4 -1: int2 +4 -1: int3 +119 -1: (Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;I)Lsun/reflect/MethodAccessor; +7 -1: variant +39 -1: Lsun/reflect/annotation/AnnotationType; +11 -1: arrayOffset +24 -1: ()Ljava/util/LinkedList; +31 -1: java/lang/ClassCircularityError +17 -1: java/lang/Package +10 -1: ccsid00858 +27 -1: java/io/ExpiringCache$Entry +16 -1: newFieldAccessor +67 -1: (Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object; +99 -1: Lsun/reflect/generics/repository/GenericDeclRepository; +53 -1: (Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)V +53 -1: Ljava/util/concurrent/ConcurrentHashMap$Node; +58 -1: ([TT;)Ljava/util/stream/Stream; +54 -1: (Ljava/lang/CharSequence;Ljava/text/Normalizer$Form;)Z +8 -1: Kerberos +29 -1: ()Ljava/nio/channels/Channel; +12 -1: java_version +45 -1: (Lsun/reflect/DelegatingMethodAccessorImpl;)V +10 -1: canConvert +136 -1: (Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V +26 -1: getDayOfWeekDateOnOrBefore +7 -1: INVALID +10 -1: TERMINATED +41 -1: Ljava/security/cert/CertificateException; +74 -1: (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/String; +30 -1: [Ljava/lang/invoke/MethodType; +13 -1: getMethodName +7 -1: Factory +34 -1: (Ljava/util/function/BiConsumer;)V +11 -1: unlinkFirst +37 -1: lambda$getDeclaredAnnotationsByType$0 +77 -1: (Ljava/nio/ByteBuffer;ILjava/nio/CharBuffer;II)Ljava/nio/charset/CoderResult; +20 -1: java/util/ArrayDeque +65 -1: (Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;J)V +49 -1: (Ljava/util/ArrayDeque;Ljava/util/ArrayDeque$1;)V +22 -1: (J)Ljava/time/Instant; +17 -1: URLClassPath.java +6 -1: 8859_1 +25 -1: stopRemoteManagementAgent +6 -1: 8859_2 +17 -1: containsNullValue +6 -1: 8859_4 +6 -1: 8859_5 +26 -1: (Ljava/nio/ByteBuffer;IC)V +76 -1: (Ljava/lang/Runnable;Ljava/security/AccessControlContext;)Ljava/lang/Thread; +6 -1: 8859_7 +6 -1: 8859_9 +8 -1: setHours +9 -1: File.java +21 -1: isIdentifierIgnorable +5 -1: ([C)I +4 -1: (B)I +10 -1: codesource +77 -1: ([Ljava/net/URL;Ljava/lang/ClassLoader;Ljava/security/AccessControlContext;)V +4 -1: (B)J +6 -1: isFair +30 -1: java/lang/NullPointerException +10 -1: IMPL_NAMES +13 -1: Runnable.java +26 -1: Ill-formed extension key: +17 -1: ()[Ljava/io/File; +18 -1: javaSecurityAccess +16 -1: equalsIgnoreCase +4 -1: (B)V +5 -1: ([C)V +25 -1: Ljava/io/FileInputStream; +14 -1: trackJavaUsage +20 -1: Ljava/io/FileSystem; +10 -1: iso_8859_1 +4 -1: (B)Z +30 -1: java/lang/NoClassDefFoundError +152 -1: (Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode; +19 -1: java/lang/Cloneable +55 -1: ([Ljava/lang/Object;Ljava/util/function/IntFunction;I)V +27 -1: (Ljava/nio/ByteBuffer;IJZ)V +21 -1: ()Lsun/misc/JarIndex; +72 -1: ([Ljava/security/CodeSource;)Ljava/util/Enumeration; +64 -1: (Ljava/util/Collection;Ljava/util/Comparator;)Ljava/lang/Object; +20 -1: invalid entry crc-32 +9 -1: BASECOUNT +29 -1: java/security/BasicPermission +52 -1: (Ljava/lang/String;Ljava/lang/String;)Ljava/io/File; +7 -1: ([B[B)Z +17 -1: EMPTY_ELEMENTDATA +61 -1: (Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object; +49 -1: (ILjava/lang/Class;)Ljava/lang/invoke/MethodType; +29 -1: sun/reflect/MagicAccessorImpl +121 -1: (Ljava/lang/String;Lsun/reflect/generics/factory/GenericsFactory;)Lsun/reflect/generics/repository/ConstructorRepository; +6 -1: ([II)I +40 -1: (Ljava/lang/String;I)Ljava/lang/Integer; +25 -1: java.content.handler.pkgs +63 -1: ()Ljava/util/Set;>; +13 -1: parameterList +6 -1: rebind +16 -1: isSuperInterface +6 -1: ([II)V +14 -1: currentRuntime +9 -1: BA_EXISTS +15 -1: END_PUNCTUATION +15 -1: no such method +19 -1: getAndVerifyPackage +4 -1: wrap +24 -1: checkAwtEventQueueAccess +7 -1: ibm-437 +4 -1: open +47 -1: (Ljava/nio/ByteBuffer;[BI)Ljava/nio/ByteBuffer; +21 -1: ADDRESS_BITS_PER_WORD +13 -1: isConstructor +12 -1: getUseCaches +27 -1: sun/util/locale/LocaleUtils +4 -1: koi8 +23 -1: getParameterAnnotations +9 -1: providers +57 -1: ([Ljava/lang/Object;Ljava/util/function/BinaryOperator;)V +24 -1: Lsun/misc/JavaNetAccess; +22 -1: ([J)Ljava/lang/String; +7 -1: p-1022$ +6 -1: isType +63 -1: Ljava/util/Map; +21 -1: pageAlignDirectMemory +18 -1: getManifestDigests +37 -1: [Ljava/lang/reflect/AccessibleObject; +7 -1: decrypt +54 -1: (Lsun/misc/URLClassPath$JarLoader;)Ljava/util/HashMap; +32 -1: lambda$comparingByKey$bbdbfea9$1 +21 -1: hasGenericInformation +31 -1: java/nio/charset/CharsetEncoder +15 -1: setTargetNormal +3 -1: ulp +18 -1: argumentTypesMatch +12 -1: getDayOfYear +8 -1: closeAll +76 -1: Ljava/lang/ref/SoftReference; +6 -1: concat +9 -1: getLongAt +16 -1: hasBeenFinalized +32 -1: [Ljava/util/Hashtable$Entry<**>; +23 -1: CheckedRandomAccessList +106 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/net/URI; +21 -1: defineClassInPackage. +11 -1: ([III[III)V +8 -1: toZoneId +34 -1: SUBCLASS_IMPLEMENTATION_PERMISSION +55 -1: java/util/concurrent/atomic/AtomicReferenceFieldUpdater +8 -1: isDirect +10 -1: ALL_ACCESS +12 -1: isRegistered +29 -1: ForEachTransformedMappingTask +5 -1: LIJFD +23 -1: (Ljava/util/TimeZone;)V +23 -1: (Ljava/util/TimeZone;)Z +20 -1: java/lang/Appendable +29 -1: Lsun/util/calendar/Gregorian; +9 -1: charValue +8 -1: ONE_HOUR +38 -1: (Ljava/util/Locale;)Ljava/lang/String; +7 -1: script= +10 -1: X-UTF-16LE +7 -1: ENTRIES +6 -1: detach +38 -1: certpath PKIX CertPathBuilder and +14 -1: setLanguageTag +13 -1: isAlphaString +13 -1: interpretName +9 -1: dayOfWeek +88 -1: (Ljava/lang/Class;ZLjava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/util/List; +91 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;)Ljava/lang/invoke/MethodHandle; +13 -1: addTypeString +17 -1: VectorSpliterator +12 -1: MILLISECONDS +6 -1: CENCOM +10 -1: KeySetView +18 -1: getTargetException +7 -1: H_ALPHA +32 -1: sun/util/locale/BaseLocale$Cache +25 -1: [Ljava/lang/CharSequence; +7 -1: Builder +4 -1: left +19 -1: BootClassPathHolder +12 -1: publicFields +11 -1: windows-437 +9 -1: EMPTY_SET +26 -1: GET_STACK_TRACE_PERMISSION +6 -1: copyOf +14 -1: aliases_IBM737 +9 -1: writeLong +35 -1: (JLjava/util/concurrent/TimeUnit;)Z +70 -1: Ljava/lang/Object;Ljava/security/PrivilegedAction; +22 -1: getAnnotatedReturnType +41 -1: (Ljava/lang/String;[BII)Ljava/lang/Class; +8 -1: ,maxpri= +29 -1: handleParameterNumberMismatch +26 -1: ts timestamping +11 -1: checkListen +10 -1: SourceFile +44 -1: (Ljava/lang/String;)Ljava/util/jar/JarEntry; +17 -1: weakCompareAndSet +9 -1: timestamp +21 -1: (Z)Ljava/lang/String; +12 -1: doneWithMeta +20 -1: makeCollectArguments +52 -1: (JLjava/util/function/BiFunction;)Ljava/lang/Object; +10 -1: searchKeys +48 -1: sun/reflect/SerializationConstructorAccessorImpl +69 -1: (Ljava/lang/reflect/Constructor<*>;)Lsun/reflect/ConstructorAccessor; +19 -1: ()Lsun/misc/Unsafe; +11 -1: deepEquals0 +7 -1: GB18030 +13 -1: ValueIterator +75 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +28 -1: java/util/PropertyPermission +6 -1: CENCRC +3 -1: url +3 -1: L_L +19 -1: Certificate too big +33 -1: sun/reflect/DelegatingClassLoader +16 -1: lambda$stream$57 +11 -1: BitSet.java +13 -1: sun/misc/Perf +26 -1: Ljava/util/SimpleTimeZone; +7 -1: (BBBB)I +24 -1: sun/misc/FloatingDecimal +21 -1: sun/util/PreHashedMap +8 -1: utf-16be +11 -1: isInherited +83 -1: (Ljava/util/Properties;Ljava/io/OutputStream;Ljava/lang/String;Ljava/lang/String;)V +52 -1: (Ljava/lang/Class;Ljava/security/ProtectionDomain;)V +11 -1: getDoOutput +18 -1: asVarargsCollector +22 -1: NoSuchMethodError.java +18 -1: getStackTraceDepth +30 -1: (Ljava/io/File;)Ljava/net/URL; +15 -1: CURRENCY_SYMBOL +24 -1: Lsun/misc/JavaNioAccess; +6 -1: NATIVE +22 -1: Lsun/misc/PerfCounter; +63 -1: java/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask +30 -1: less than Character.MIN_RADIX +17 -1: isCallerSensitive +8 -1: shutdown +11 -1: STATE_GREEN +4 -1: next +10 -1: tryPresize +16 -1: CONSTRUCTOR_NAME +3 -1: MAY +21 -1: java.security.manager +20 -1: Lsun/misc/Contended; +16 -1: DISPLAY_LANGUAGE +6 -1: KeySet +9 -1: getScript +3 -1: utc +17 -1: TRACE_INTERPRETER +39 -1: (Ljava/lang/Object;I)Ljava/lang/String; +19 -1: getFieldAtIfLoaded0 +15 -1: methodFilterMap +54 -1: Ljava/util/Map; +45 -1: java/security/cert/Certificate$CertificateRep +43 -1: (Ljava/lang/String;)Lsun/util/calendar/Era; +34 -1: java/security/cert/X509Certificate +19 -1: versionsInitialized +11 -1: isDirectory +14 -1: aliases_IBM775 +38 -1: (Ljava/util/function/Consumer<-TE;>;)V +38 -1: (Ljava/lang/String;)Ljava/util/Locale; +40 -1: (Ljava/lang/String;Z)Lsun/misc/Resource; +14 -1: setDefaultZone +14 -1: highResCounter +78 -1: (Ljava/lang/ClassValue$Version;Ljava/lang/Object;)Ljava/lang/ClassValue$Entry; +16 -1: defaultUseCaches +40 -1: (Ljava/util/zip/ZipFile;)Ljava/util/Map; +24 -1: isSupplementaryCodePoint +15 -1: ISO_8859_1.java +13 -1: multiplyExact +126 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lsun/util/locale/LocaleExtensions;)Ljava/util/Locale; +8 -1: classMap +8 -1: wildcard +19 -1: getSimpleBinaryName +17 -1: illegal signature +14 -1: == basicType( +17 -1: ZipConstants.java +32 -1: [Ljava/lang/VirtualMachineError; +27 -1: ()Ljava/util/stream/Stream; +24 -1: (Ljava/lang/Exception;)V +21 -1: java/util/Enumeration +13 -1: newSetFromMap +8 -1: getenv.* +20 -1: sun/management/Agent +21 -1: sun/nio/cs/US_ASCII$1 +7 -1: comment +15 -1: appendAuthority +11 -1: hasWrappers +10 -1: dstOffset +24 -1: sun/reflect/ConstantPool +75 -1: (Ljava/util/jar/JarFile;[Ljava/security/CodeSource;)Ljava/util/Enumeration; +52 -1: (Ljava/util/jar/JarFile;)Ljava/util/jar/JarVerifier; +70 -1: Ljava/lang/Object;Ljava/security/PrivilegedAction; +14 -1: previousSetBit +17 -1: AF_GETSTATIC_INIT +15 -1: ArrayDeque.java +7 -1: boolean +25 -1: (I)Ljava/math/BigInteger; +146 -1: (Ljava/lang/ref/ReferenceQueue;>;Ljava/util/concurrent/ConcurrentMap<+Ljava/lang/ref/WeakReference;>;*>;)V +8 -1: getClass +8 -1: user.dir +6 -1: VALUES +5 -1: raise +39 -1: (JLjava/util/function/Consumer<-TV;>;)V +107 -1: Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater; +5 -1: print +8 -1: readChar +55 -1: (JLjava/util/TimeZone;)Lsun/util/calendar/CalendarDate; +56 -1: java/util/concurrent/ConcurrentHashMap$MapReduceKeysTask +60 -1: Ljava/lang/Number;Ljava/lang/Comparable; +102 -1: (Ljava/util/SortedMap;)Ljava/util/SortedMap; +23 -1: printModifiersIfNonzero +14 -1: getterFunction +15 -1: ISO-10646-UCS-2 +14 -1: canonizeString +13 -1: getTotalSpace +24 -1: synchronizedNavigableSet +100 -1: (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)TT; +4 -1: ioex +24 -1: ()Ljava/nio/FloatBuffer; +14 -1: toBinaryString +7 -1: Segment +34 -1: ()Lsun/misc/JavaUtilZipFileAccess; +17 -1: setTargetVolatile +22 -1: (Ljava/util/List<*>;)V +51 -1: (ILjava/lang/CharSequence;)Ljava/lang/StringBuffer; +22 -1: (Ljava/util/List<*>;)Z +5 -1: (FI)F +11 -1: parseMethod +8 -1: Compiled +19 -1: java/util/SortedMap +7 -1: setByte +12 -1: getFieldType +8 -1: pageSize +14 -1: getCallerClass +9 -1: ensureObj +18 -1: refKindHasReceiver +10 -1: getZoneIds +24 -1: (Ljava/nio/CharBuffer;)I +47 -1: ()Lsun/reflect/generics/parser/SignatureParser; +8 -1: getIndex +24 -1: (Ljava/lang/Thread;TT;)V +18 -1: (Ljava/util/Map;)V +18 -1: (Ljava/util/Map;)Z +6 -1: random +10 -1: putAddress +64 -1: (Ljava/util/function/Consumer<-Ljava/util/Map$Entry;>;)V +24 -1: (Ljava/nio/CharBuffer;)V +8 -1: canCache +24 -1: (Ljava/nio/CharBuffer;)Z +9 -1: getIntAt0 +4 -1: sqrt +8 -1: makeLong +54 -1: ([Ljava/lang/Object;Ljava/util/function/IntFunction;)V +5 -1: (JJ)I +26 -1: javaIOFileDescriptorAccess +5 -1: (JJ)J +15 -1: != basicType: +36 -1: Ljava/lang/ref/ReferenceQueue<-TT;>; +5 -1: words +16 -1: sun.jnu.encoding +32 -1: (Ljava/lang/invoke/LambdaForm;)V +22 -1: ensureClassInitialized +16 -1: Ljava/util/List; +14 -1: varargsInvoker +5 -1: (JJ)V +20 -1: java/util/Properties +12 -1: getImplClass +21 -1: argumentTypesToString +5 -1: (JJ)Z +50 -1: java/util/Collections$SynchronizedRandomAccessList +17 -1: makeWrappedMember +21 -1: UnmodifiableSortedSet +22 -1: (ILjava/lang/Class;Z)V +3 -1: MIT +13 -1: bootClassPath +50 -1: (JLjava/util/function/Function;)Ljava/lang/Object; +74 -1: Ljava/util/HashMap$Node; +45 -1: (Ljava/util/Map$Entry;Ljava/util/Map$Entry;)I +12 -1: advanceProbe +10 -1: encoderFor +14 -1: DataInput.java +16 -1: java/lang/Double +3 -1: 912 +3 -1: 914 +3 -1: abs +3 -1: 915 +13 -1: currentThread +17 -1: ClassDefiner.java +32 -1: sun/misc/Launcher$ExtClassLoader +16 -1: Current state = +12 -1: elementCount +10 -1: unmaskNull +8 -1: csibm857 +32 -1: java/net/UnknownServiceException +10 -1: x-utf-16be +3 -1: acc +37 -1: Ljava/util/List; +23 -1: ([Ljava/lang/Thread;Z)I +17 -1: impliesIgnoreMask +23 -1: getGenericComponentType +51 -1: ()Lsun/reflect/generics/repository/ClassRepository; +34 -1: " not found. Will use interpreter. +38 -1: ()Ljava/security/AccessControlContext; +6 -1: final +8 -1: utf-16le +3 -1: 920 +3 -1: 923 +5 -1: (I)[C +43 -1: (Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer; +8 -1: csibm862 +34 -1: (Ljava/lang/ref/Reference<+TT;>;)Z +8 -1: csibm866 +20 -1: getParameterizedType +7 -1: (II[C)V +20 -1: [Ljava/lang/Package; +84 -1: (Ljava/lang/String;Ljava/security/ProtectionDomain;)Ljava/security/ProtectionDomain; +28 -1: SynchronizedRandomAccessList +18 -1: sun/misc/VMSupport +61 -1: java/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry +3 -1: add +16 -1: ZipEntryIterator +11 -1: next_target +87 -1: (Ljava/lang/String;Ljava/nio/ByteBuffer;Ljava/security/CodeSource;)Ljava/lang/Class<*>; +4 -1: amod +12 -1: markedSkipLF +55 -1: java/util/concurrent/ConcurrentHashMap$EntrySpliterator +5 -1: lim= +29 -1: java/security/PermissionsHash +50 -1: (Ljava/lang/CharSequence;II)Ljava/lang/Appendable; +19 -1: makePairwiseConvert +58 -1: (Ljava/lang/ClassValue$Entry;)V +8 -1: contents +11 -1: user.region +17 -1: RandomAccess.java +13 -1: singletonList +13 -1: policy,access +64 -1: Ljava/util/Map; +25 -1: (Ljava/lang/Appendable;)V +19 -1: (Ljava/util/List;)V +43 -1: (Ljava/lang/ClassLoader;Ljava/lang/Class;)V +19 -1: (Ljava/util/List;)Z +15 -1: America/Chicago +25 -1: (II)Ljava/nio/CharBuffer; +12 -1: getDayOfWeek +8 -1: ([BIIZ)V +28 -1: (Ljava/lang/reflect/Field;)I +28 -1: (Ljava/lang/reflect/Field;)J +18 -1: getDeclaringClass0 +11 -1: counterTime +30 -1: (Ljava/util/Collection;)V +28 -1: (Ljava/lang/reflect/Field;)V +31 -1: (IIIILjava/io/FileDescriptor;)V +25 -1: java/net/SocketPermission +20 -1: bad parameter count +18 -1: getHeaderFieldLong +26 -1: GetReflectionFactoryAction +19 -1: MIN_TRANSFER_STRIDE +17 -1: java/nio/Bits$1$1 +7 -1: getSize +33 -1: java/util/function/ToLongFunction +46 -1: (IILjava/lang/String;)Ljava/lang/StringBuffer; +10 -1: access$800 +65 -1: sun/misc/JavaSecurityProtectionDomainAccess$ProtectionDomainCache +26 -1: (Ljava/lang/ClassLoader;)V +25 -1: java/util/IdentityHashMap +26 -1: (Ljava/lang/ClassLoader;)Z +91 -1: (Ljava/util/function/ToIntFunction<-TT;>;)Ljava/util/Comparator; +26 -1: ([CIILjava/lang/String;I)I +12 -1: canonicalize +3 -1: val +8 -1: putCharB +12 -1: UTF_32LE_BOM +60 -1: (Ljava/security/CodeSource;)Ljava/security/ProtectionDomain; +44 -1: (Lsun/misc/SignalHandler;Lsun/misc/Signal;)V +26 -1: (Ljava/util/Enumeration;)V +11 -1: INVALIDATED +8 -1: putCharL +22 -1: (II)Ljava/lang/String; +7 -1: hasNext +5 -1: WRITE +20 -1: MIN_INITIAL_CAPACITY +13 -1: propertyNames +9 -1: Gregorian +13 -1: getExpiration +7 -1: minutes +7 -1: ostream +9 -1: java.lang +17 -1: forceStandardTime +9 -1: initWords +41 -1: java/lang/Thread$UncaughtExceptionHandler +9 -1: theUnsafe +27 -1: ForEachTransformedEntryTask +10 -1: forEncoder +31 -1: needsClassLoaderPermissionCheck +5 -1: ctime +25 -1: ()Ljava/nio/DoubleBuffer; +8 -1: getValue +66 -1: (Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale$Key; +42 -1: (Ljava/io/InputStream;Ljava/lang/String;)V +6 -1: august +14 -1: compileClasses +13 -1: javaNetAccess +22 -1: interpretWithArguments +4 -1: url: +14 -1: EMPTY_ITERATOR +60 -1: Ljava/util/WeakHashMap; +24 -1: java/util/jar/Attributes +12 -1: getOrDefault +19 -1: Pacific/Guadalcanal +33 -1: ()Ljava/lang/reflect/Constructor; +38 -1: java/util/Collections$UnmodifiableList +13 -1: basicTypeChar +22 -1: (Ljava/lang/String;J)J +14 -1: memberDefaults +42 -1: (Ljava/lang/Class<*>;[Ljava/lang/String;)V +38 -1: (Ljava/util/function/Consumer<-TK;>;)V +16 -1: LF_NEWINVSPECIAL +10 -1: classDepth +28 -1: [Ljava/io/ObjectStreamField; +46 -1: (Ljava/util/Collection;)Ljava/util/Collection; +91 -1: ([Ljava/lang/reflect/Method;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method; +11 -1: getLocation +39 -1: (Ljava/lang/Class;[Ljava/lang/Class;Z)V +9 -1: loadTable +55 -1: Directory separator should not appear in library name: +7 -1: setTime +14 -1: getConstructor +4 -1: urls +25 -1: dispatchUncaughtException +77 -1: (ILjava/lang/Object;Ljava/lang/Class<*>;)Ljava/util/HashMap$TreeNode; +8 -1: modCount +8 -1: Opening +6 -1: ENDHDR +4 -1: cnfe +34 -1: DIRECTIONALITY_PARAGRAPH_SEPARATOR +10 -1: Asia/Amman +3 -1: MST +28 -1: DIRECTIONALITY_ARABIC_NUMBER +3 -1: all +4 -1: enum +8 -1: copyWith +12 -1: ([JI[IIJII)I +29 -1: Ljava/lang/annotation/Target; +7 -1: Thread- +14 -1: x-utf-32le-bom +38 -1: (ILjava/lang/management/MemoryUsage;)V +33 -1: Signal already used by VM or OS: +27 -1: (I)Ljava/lang/StringBuffer; +25 -1: java/text/Normalizer$Form +10 -1: x-utf-16le +34 -1: can not access a member of class +27 -1: (Ljava/nio/ByteBuffer;IFZ)V +28 -1: (Ljava/lang/ClassValue<*>;)V +16 -1: INITIAL_CAPACITY +23 -1: DirectMethodHandle.java +18 -1: reduceValuesToLong +41 -1: (Ljava/lang/String;Ljava/lang/Class<*>;)V +6 -1: unwrap +12 -1: threadStatus +5 -1: (DI)D +11 -1: fieldOffset +52 -1: java/util/concurrent/ConcurrentHashMap$EntryIterator +14 -1: ACCESS_EXECUTE +44 -1: (Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer; +29 -1: ([Ljava/lang/ThreadGroup;IZ)I +18 -1: LocalVariableTable +17 -1: ConstantPool.java +26 -1: (Ljava/nio/ByteBuffer;ID)V +4 -1: (C)B +3 -1: and +4 -1: head +126 -1: (Ljava/lang/reflect/GenericDeclaration;Lsun/reflect/generics/scope/Scope;)Lsun/reflect/generics/factory/CoreReflectionFactory; +4 -1: (C)C +16 -1: Pacific/Auckland +7 -1: Thread[ +5 -1: ([D)I +4 -1: (C)I +98 -1: ([Ljava/lang/reflect/Constructor;)[Ljava/lang/reflect/Constructor; +11 -1: fileHandler +30 -1: DIRECTIONALITY_NONSPACING_MARK +10 -1: (this Map) +14 -1: malformedCache +5 -1: ([D)V +4 -1: (C)V +26 -1: getUnicodeLocaleAttributes +4 -1: (C)Z +81 -1: (JLjava/util/function/ToLongBiFunction;JLjava/util/function/LongBinaryOperator;)J +46 -1: [Ljava/util/concurrent/ConcurrentHashMap$Node; +20 -1: Max. Heap Size: +24 -1: Ljava/lang/reflect/Type; +13 -1: EmptyIterator +8 -1: allocate +7 -1: FLUSHED +8 -1: exitVM.* +59 -1: (Ljava/lang/String;)Lsun/util/locale/InternalLocaleBuilder; +19 -1: reduceEntriesToLong +15 -1: getISOLanguages +13 -1: CONSTANT_ZERO +23 -1: (I)Ljava/util/Iterator; +96 -1: Ljava/util/AbstractMap;Ljava/util/Map; +11 -1: isSynthetic +7 -1: lineBuf +30 -1: java/lang/annotation/Inherited +65 -1: Ljava/lang/Object;Ljava/lang/Iterable; +35 -1: (Ljava/lang/String;)[Ljava/io/File; +27 -1: java/security/cert/CertPath +26 -1: startRemoteManagementAgent +9 -1: shiftLeft +5 -1: stack +42 -1: (Ljava/lang/Class<*>;[Ljava/lang/Object;)V +11 -1: CheckedList +10 -1: replaceAll +86 -1: (Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode; +24 -1: (I)Ljava/nio/CharBuffer; +13 -1: image/vnd.fpx +15 -1: iso_8859-1:1987 +19 -1: (Ljava/lang/Long;)I +22 -1: sun/misc/SignalHandler +15 -1: ifModifiedSince +42 -1: (Ljava/lang/Class;)Ljava/lang/ClassLoader; +105 -1: (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Class;I[Ljava/lang/invoke/MemberName;)I +22 -1: Negative timeout value +38 -1: Ljava/io/UnsupportedEncodingException; +11 -1: removeRange +13 -1: Compiler.java +6 -1: Sorter +8 -1: aliasSet +10 -1: UNASSIGNED +34 -1: lambda$comparingByValue$1065357e$1 +34 -1: ()Ljava/lang/Class$AnnotationData; +25 -1: sun/misc/Launcher$Factory +15 -1: getLongVolatile +8 -1: vmloader +10 -1: unicodebig +10 -1: closeables +31 -1: JavaIOFileDescriptorAccess.java +7 -1: static +3 -1: arg +21 -1: library can't be null +42 -1: java/util/ArraysParallelSortHelpers$FJByte +22 -1: getDeclaringExecutable +19 -1: runFinalizersOnExit +20 -1: simpleTimeZoneParams +13 -1: Modifier.java +14 -1: pkcs11keystore +6 -1: shared +30 -1: java/net/MalformedURLException +26 -1: ()[Lsun/util/calendar/Era; +13 -1: x-MS950-HKSCS +10 -1: relativize +40 -1: (Ljava/lang/String;JJ)Ljava/lang/String; +31 -1: java/util/HashMap$ValueIterator +29 -1: MODIFY_THREADGROUP_PERMISSION +38 -1: (Ljava/lang/String;)Ljava/lang/Object; +7 -1: destroy +37 -1: (Ljava/util/List;)[Ljava/lang/String; +18 -1: (Ljava/io/File;Z)V +32 -1: Ljava/util/HashMap$Node; +18 -1: interfaceModifiers +34 -1: java/util/LinkedList$LLSpliterator +7 -1: REF_??? +23 -1: java/net/ContentHandler +20 -1: +17 -1: [Ljava/lang/Byte; +6 -1: exitVM +3 -1: att +27 -1: sun/nio/cs/UTF_16BE$Encoder +6 -1: exists +28 -1: Ljava/util/Collection<+TE;>; +48 -1: (Ljava/lang/CharSequence;)Ljava/lang/Appendable; +6 -1: getMap +52 -1: ([Ljava/lang/Class;I)Ljava/lang/reflect/Constructor; +11 -1: stackTrace[ +21 -1: slowCheckMemberAccess +33 -1: ReflectiveOperationException.java +9 -1: versionId +56 -1: Wrong number of parameters in MethodParameters attribute +14 -1: isLowSurrogate +8 -1: csPCp852 +16 -1: copyConstructors +25 -1: ()Ljava/util/Spliterator; +9 -1: closeLock +17 -1: readUnsignedShort +7 -1: 8859_13 +7 -1: 8859_15 +13 -1: TARGET_OFFSET +26 -1: (Ljava/util/Hashtable;IZ)V +44 -1: (Ljava/nio/CharBuffer;)Ljava/nio/CharBuffer; +46 -1: (Ljava/lang/reflect/Type;)Ljava/lang/Class<*>; +25 -1: DEFAULT_CONCURRENCY_LEVEL +36 -1: Ljava/util/List; +29 -1: sun.nio.PageAlignDirectMemory +37 -1: (Ljava/lang/Class;I)Ljava/lang/Class; +12 -1: encryptBlock +8 -1: parentOf +5 -1: H_HEX +11 -1: getFloatAt0 +24 -1: VirtualMachineError.java +18 -1: getDeclaredClasses +59 -1: (Ljava/lang/AbstractStringBuilder;)Ljava/lang/StringBuffer; +42 -1: (Ljava/util/List;>;)[C +37 -1: (Ljava/lang/String;)Ljava/lang/Float; +13 -1: Iterator.java +25 -1: (Ljava/io/PrintStream;I)V +9 -1: getObject +19 -1: [Ljava/lang/String; +7 -1: SIZECTL +11 -1: isUnderflow +27 -1: sun.nio.MaxDirectMemorySize +21 -1: isNonPublicProxyClass +13 -1: toCalendarDOW +9 -1: Type.java +14 -1: aliases_IBM850 +17 -1: emptyNavigableMap +14 -1: aliases_IBM852 +14 -1: aliases_IBM855 +14 -1: aliases_IBM857 +14 -1: aliases_IBM858 +15 -1: iso_8859-4:1988 +13 -1: UnicodeScript +8 -1: getCharB +17 -1: constructorMethod +27 -1: java/util/function/Function +20 -1: getProtectionDomain0 +8 -1: getCharL +32 -1: ([Ljava/io/File;)[Ljava/net/URL; +51 -1: (Ljava/lang/Class;Z)Ljava/lang/invoke/MethodHandle; +7 -1: getenv. +5 -1: stale +14 -1: aliases_IBM862 +32 -1: java/util/spi/LocaleNameProvider +14 -1: aliases_IBM866 +51 -1: ([Ljava/lang/Class;)Ljava/lang/reflect/Constructor; +6 -1: CENDSK +36 -1: java/util/Comparators$NullComparator +34 -1: UnsafeStaticFieldAccessorImpl.java +17 -1: staticFieldOffset +12 -1: prefetchRead +4 -1: help +34 -1: (Ljava/util/concurrent/TimeUnit;)J +8 -1: getChars +19 -1: java/lang/Throwable +34 -1: Annotation Type:\n Member types: +55 -1: (Ljava/lang/Class<*>;Ljava/security/ProtectionDomain;)V +14 -1: aliases_IBM874 +17 -1: getDisplayVariant +24 -1: Ljava/net/NetPermission; +15 -1: jvmMinorVersion +11 -1: subSequence +3 -1: x86 +6 -1: double +14 -1: checkSlotCount +20 -1: java/net/InetAddress +14 -1: Principal.java +8 -1: $,;:@&=+ +17 -1: ByteBuffered.java +21 -1: sun.misc.Perf.getPerf +11 -1: finishEntry +27 -1: sun.timezone.ids.oldmapping +26 -1: (ZLjava/io/OutputStream;)V +41 -1: (Ljava/lang/String;Z)Ljava/lang/Class<*>; +32 -1: generateSerializationConstructor +6 -1: Value +40 -1: (Ljava/lang/String;Ljava/lang/String;Z)V +16 -1: previousClearBit +7 -1: theProp +51 -1: (Ljava/io/OutputStream;Ljava/nio/charset/Charset;)V +39 -1: com.sun.javafx.application.LauncherImpl +21 -1: URLStreamHandler.java +4 -1: in +14 -1: BIT_INDEX_MASK +125 -1: (Ljava/util/Comparator<-TK;>;)Ljava/util/Comparator;>; +49 -1: (Ljava/util/Set;Ljava/lang/Class;)Ljava/util/Set; +10 -1: scaleValue +27 -1: (Ljava/nio/ByteBuffer;IDZ)V +78 -1: (Ljava/util/Collection;[Ljava/lang/reflect/Field;)V +53 -1: (I)Ljava/util/Enumeration; +38 -1: java/lang/IncompatibleClassChangeError +60 -1: java/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask +23 -1: not a method or field: +35 -1: Ljava/nio/BufferUnderflowException; +4 -1: i386 +13 -1: US_ASCII.java +80 -1: ([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/lang/reflect/AnnotatedType; +21 -1: initializeSystemClass +6 -1: ([CI)I +18 -1: getBooleanProperty +35 -1: java/util/function/ToDoubleFunction +37 -1: (Ljava/lang/String;)Ljava/lang/Class; +28 -1: MapReduceEntriesToDoubleTask +38 -1: java/util/LinkedHashMap$LinkedEntrySet +8 -1: copySign +6 -1: ([CI)V +55 -1: sun/util/calendar/ZoneInfoFile$ZoneOffsetTransitionRule +12 -1: parseBoolean +3 -1: NET +3 -1: NEW +6 -1: Values +17 -1: getJavaLangAccess +9 -1: LocaleKey +3 -1: :-1 +30 -1: (Ljava/io/ObjectInputStream;)V +3 -1: NFC +3 -1: NFD +18 -1: SIMPLIFIED_CHINESE +28 -1: ()Ljava/lang/reflect/Method; +9 -1: localInit +37 -1: sun/util/locale/LocaleSyntaxException +15 -1: LambdaForm.java +5 -1: rtype +8 -1: field " +50 -1: (Ljava/lang/Class;Ljava/lang/ref/ReferenceQueue;)V +80 -1: (Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;IILjava/lang/String;[B[B)V +36 -1: java/lang/invoke/MethodHandleNatives +22 -1: (Ljava/util/Map<**>;)Z +22 -1: Ljava/lang/Class; +7 -1: SubList +14 -1: connect,accept +19 -1: declaredAnnotations +38 -1: Ljava/lang/ThreadLocal$ThreadLocalMap; +11 -1: isSpaceChar +10 -1: offerFirst +20 -1: sun/nio/ByteBuffered +17 -1: packageDefinition +7 -1: trigger +35 -1: [Ljava/lang/invoke/LambdaForm$Name; +19 -1: sun.stdout.encoding +5 -1: start +26 -1: (Ljava/util/HashMap;IIII)V +65 -1: (JLjava/util/function/Consumer<-Ljava/util/Map$Entry;>;)V +6 -1: LOCVER +3 -1: :// +42 -1: (CLjava/lang/Class<*>;Ljava/lang/Object;)Z +6 -1: friday +45 -1: sun/reflect/DelegatingConstructorAccessorImpl +15 -1: iso_8859-7:1987 +15 -1: newCalendarDate +24 -1: getAnnotatedReceiverType +32 -1: java/util/NoSuchElementException +50 -1: (Ljava/util/NavigableSet;)Ljava/util/NavigableSet; +26 -1: java/text/SimpleDateFormat +16 -1: threadInitNumber +55 -1: (TT;)Ljava/util/Spliterator; +23 -1: (Ljava/lang/Object;)TT; +3 1: bar +37 -1: getFunctionalInterfaceMethodSignature +5 -1: state +39 -1: [Ljava/lang/reflect/GenericDeclaration; +22 -1: sun/net/ProgressSource +13 -1: LLSpliterator +93 -1: Ljava/lang/Object;Ljava/util/Enumeration;Ljava/util/Iterator; +5 -1: JAPAN +11 -1: SPACE_TOTAL +20 -1: CharsetProvider.java +12 -1: CR_UNDERFLOW +7 -1: ITALIAN +11 -1: getCallerPD +13 -1: isMemberClass +38 -1: (Ljava/util/function/Consumer<-TT;>;)V +18 -1: malformedForLength +14 -1: ReflectionData +34 -1: (BZI)Ljava/lang/invoke/LambdaForm; +16 -1: forPrimitiveType +31 -1: field found in java.lang.Class +60 -1: (Ljava/lang/Void;Ljava/lang/ThreadGroup;Ljava/lang/String;)V +18 -1: DescendingIterator +25 -1: (IZLjava/lang/Runnable;)V +35 -1: ()[Ljava/lang/reflect/TypeVariable; +3 -1: bcp +23 -1: (Ljava/lang/Object;)TV; +25 -1: setDefaultAssertionStatus +10 -1: ([BIIIII)V +150 -1: (Ljava/util/concurrent/ConcurrentHashMap$Node;)Ljava/util/concurrent/ConcurrentHashMap$Node; +14 -1: Inherited: +17 -1: fileTimeToWinTime +7 -1: ([BI)[B +26 -1: java/io/OutputStreamWriter +58 -1: (Ljava/util/ListIterator<+TT;>;I)TT; +39 -1: sun/reflect/annotation/AnnotationParser +71 -1: (Ljava/nio/file/Path;Ljava/lang/String;)Ljava/nio/file/DirectoryStream; +47 -1: Ljava/util/concurrent/locks/ReentrantLock$Sync; +44 -1: (Ljava/util/Collection;[Ljava/lang/Object;)Z +43 -1: ([ILjava/util/function/IntBinaryOperator;)V +29 -1: reverseAllValidSurrogatePairs +20 -1: Ljava/nio/file/Path; +20 -1: getGenericSignature0 +42 -1: (Ljava/lang/String;Ljava/lang/Class<*>;Z)V +8 -1: manEntry +64 -1: (Ljava/lang/String;)Ljava/util/Enumeration; +36 -1: newGetDoubleIllegalArgumentException +63 -1: (Ljava/util/Collection;Ljava/lang/Class;)Ljava/util/Collection; +30 -1: Ergonomics Machine Class: +40 -1: ()Ljava/util/Map; +50 -1: (Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer; +30 -1: CHECK_MEMBER_ACCESS_PERMISSION +22 -1: (Ljava/lang/Boolean;)I +10 -1: V_Variable +68 -1: java/util/concurrent/ConcurrentHashMap$ForEachTransformedMappingTask +61 -1: (Ljava/lang/String;IILjava/lang/String;)Ljava/nio/ByteBuffer; +21 -1: accessClassInPackage. +44 -1: java/util/WeakHashMap$WeakHashMapSpliterator +11 -1: nextElement +9 -1: separator +48 -1: java/util/zip/ZipFile$ZipFileInflaterInputStream +44 -1: java/security/UnresolvedPermissionCollection +10 -1: access$900 +44 -1: java/util/ArraysParallelSortHelpers$FJDouble +84 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodHandle; +52 -1: (Ljava/lang/ref/Finalizer;)Ljava/lang/ref/Finalizer; +19 -1: getDeclaredMethods0 +29 -1: (IJ)Ljava/lang/StringBuilder; +11 -1: Member.java +61 -1: (Ljava/lang/String;ZJJ)Ljava/lang/management/MemoryPoolMBean; +35 -1: java/lang/AssertionStatusDirectives +23 -1: Declaring class is null +56 -1: (Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/Object;)I +12 -1: java/io/File +41 -1: java/util/ConcurrentModificationException +47 -1: (Ljava/lang/CharSequence;)Ljava/nio/CharBuffer; +19 -1: parameterClassCache +8 -1: US_ASCII +15 -1: tryMonitorEnter +22 -1: Ljava/util/Collection; +67 -1: (Lsun/misc/Signal;Lsun/misc/SignalHandler;)Lsun/misc/SignalHandler; +27 -1: (Lsun/misc/JavaNioAccess;)V +9 -1: DigitOnes +5 -1: write +31 -1: NF_internalMemberNameEnsureInit +18 -1: comparableClassFor +20 -1: defineAnonymousClass +49 -1: (Ljava/io/InputStream;Lsun/net/ProgressSource;J)V +31 -1: java/lang/NumberFormatException +17 -1: remainderUnsigned +62 -1: ;>()Ljava/util/Comparator; +4 -1: Kind +20 -1: (Ljava/lang/Short;)I +8 -1: OfDouble +51 -1: ([Ljava/lang/Object;Ljava/lang/invoke/MethodType;)Z +22 -1: [Ljava/util/Map$Entry; +13 -1: instanceClass +29 -1: ()Ljava/lang/SecurityManager; +12 -1: isUnmappable +17 -1: getAllStackTraces +19 -1: LinkedValueIterator +7 -1: isDigit +10 -1: rangeCheck +89 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;)Ljava/util/List; +13 -1: getMethodType +21 -1: FileOutputStream.java +22 -1: ()Ljava/text/Collator; +64 -1: (Ljava/security/PrivilegedAction;)TT; +15 -1: defaultTimeZone +14 -1: emptySortedMap +35 -1: (Ljava/util/function/IntConsumer;)V +45 -1: java/util/Collections$CheckedRandomAccessList +11 -1: getPriority +7 -1: signals +6 -1: Subset +15 -1: invokeInterface +16 -1: nameRefsAreLegal +38 -1: (Ljava/lang/Object;)Ljava/lang/Object; +37 -1: Ljava/util/Collections$EmptyIterator; +9 -1: Perf.java +20 -1: java/math/BigInteger +38 -1: java/util/WeakHashMap$ValueSpliterator +71 -1: (Ljava/nio/charset/CodingErrorAction;)Ljava/nio/charset/CharsetEncoder; +50 -1: (Ljava/lang/invoke/MemberName;Ljava/lang/Object;)V +21 -1: [Ljava/lang/Class<*>; +13 -1: getProperties +63 -1: (Ljava/lang/Class<*>;[B[Ljava/lang/Object;)Ljava/lang/Class<*>; +65 -1: (Ljava/util/Set;>;)[Ljava/lang/reflect/Field; +21 -1: sun/util/calendar/Era +21 -1: Ljava/nio/CharBuffer; +23 -1: (Ljava/lang/Object;JS)V +24 -1: oracle/jrockit/jfr/VMJFR +15 -1: access allowed +34 -1: ()Lsun/util/calendar/CalendarDate; +97 -1: (Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object; +44 -1: ([Ljava/lang/Object;[Ljava/lang/Object;III)V +48 -1: (Ljava/util/Collection;I)Ljava/util/Spliterator; +11 -1: SimpleEntry +63 -1: (Ljava/net/URL;Ljava/net/URLStreamHandler;Ljava/util/HashMap;)V +8 -1: putFloat +20 -1: linkToCallSiteMethod +8 -1: invokers +35 -1: (J)Lsun/util/calendar/BaseCalendar; +6 -1: FRENCH +26 -1: getRawParameterAnnotations +9 -1: wordIndex +29 -1: JNI_COPY_FROM_ARRAY_THRESHOLD +20 -1: sun/nio/cs/Surrogate +48 -1: (Lsun/misc/JavaSecurityProtectionDomainAccess;)V +45 -1: (Ljava/lang/ThreadLocal;Ljava/lang/Object;I)V +3 -1: NST +14 -1: getHeaderField +27 -1: (Ljava/util/jar/JarFile;Z)V +10 -1: findNative +38 -1: The following can be used with access: +29 -1: convertCertArrayToSignerArray +4 -1: .DSA +12 -1: dependencies +12 -1: SYNCHRONIZED +14 -1: x-euc-jp-linux +28 -1: URLStreamHandlerFactory.java +11 -1: checkPtypes +68 -1: (Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)V +13 -1: addDayOfMonth +10 -1: isAncestor +16 -1: entryDislocation +12 -1: tableSizeFor +29 -1: (ID)Ljava/lang/StringBuilder; +19 -1: getLastRuleInstance +24 -1: getGenericParameterTypes +8 -1: ,offset= +37 -1: (Ljava/net/URL;Ljava/lang/String;II)V +13 -1: UTF_16LE.java +12 -1: setTimestamp +31 -1: AtomicReferenceFieldUpdaterImpl +6 -1: L_URIC +4 -1: (D)D +14 -1: DeqSpliterator +13 -1: LF_INVVIRTUAL +171 -1: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater; +4 -1: (D)I +22 -1: Ljava/lang/Class; +4 -1: (D)J +196 -1: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +13 -1: ,transitions= +30 -1: (Lsun/net/www/MessageHeader;)I +4 -1: (D)V +12 -1: segmentShift +4 -1: (D)Z +14 -1: Reference.java +26 -1: [Ljava/lang/reflect/Field; +26 -1: java/nio/DirectByteBufferR +31 -1: lambda$thenComparing$36697e65$1 +30 -1: (Lsun/net/www/MessageHeader;)V +55 -1: No java.nio.charset.StandardCharsets instances for you! +59 -1: (Ljava/lang/Class<*>;Ljava/lang/Object;Ljava/lang/Object;)I +19 -1: thenComparingDouble +31 -1: ()Ljava/lang/invoke/LambdaForm; +9 -1: getMillis +21 -1: StandardCharsets.java +15 -1: postDefineClass +8 -1: getExtra +3 -1: box +10 -1: nextSetBit +27 -1: java/util/ArrayList$SubList +43 -1: (Ljava/util/concurrent/ConcurrentHashMap;)V +52 -1: (Lsun/misc/URLClassPath;)Ljava/net/URLStreamHandler; +7 -1: putLong +40 -1: ;>([TT;)V +8 -1: ([DII)[D +8 -1: ([SIIS)I +8 -1: argument +12 -1: linkCallSite +56 -1: Ljava/lang/ref/WeakReference; +15 -1: returnSlotCount +68 -1: (Ljava/lang/String;[Ljava/lang/Class<*>;Z)Ljava/lang/reflect/Method; +20 -1: defaultDisplayLocale +21 -1: (Ljava/util/Vector;)V +49 -1: (Lsun/reflect/generics/visitor/TypeTreeVisitor;)V +12 -1: isAlphabetic +5 -1: perms +13 -1: dosToJavaTime +8 -1: ([SIIS)V +7 -1: valueOf +27 -1: Ljava/util/LinkedList$Node; +41 -1: (Ljava/lang/String;I)Ljava/lang/Class<*>; +38 -1: ()Ljava/nio/charset/CodingErrorAction; +4 -1: MASK +5 -1: Field +101 -1: (Ljava/lang/Class;Ljava/nio/ByteBuffer;Lsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/lang/Object; +56 -1: (Ljava/lang/String;Lsun/misc/Resource;)Ljava/lang/Class; +9 -1: SURROGATE +72 -1: (Ljava/lang/invoke/DirectMethodHandle$StaticAccessor;)Ljava/lang/Object; +19 -1: PARAMETER_MODIFIERS +48 -1: ([Ljava/lang/Object;II)Ljava/util/stream/Stream; +56 -1: (TK;TV;Ljava/util/function/BiFunction<-TV;-TV;+TV;>;)TV; +118 -1: (JLjava/util/function/BiFunction<-TK;-TV;+TU;>;Ljava/util/function/BiFunction<-TU;-TU;+TU;>;)TU; +29 -1: (Lsun/nio/ch/Interruptible;)V +45 -1: Ljava/lang/ref/Reference; +17 -1: isHeldExclusively +3 -1: NYI +15 -1: getByteVolatile +20 -1: compareAndSwapObject +29 -1: (Z)[Ljava/lang/reflect/Field; +7 -1: ([SII)V +13 -1: toLanguageTag +18 -1: StreamEncoder.java +25 -1: (IF)Ljava/nio/ByteBuffer; +18 -1: afterNodeInsertion +11 -1: accessOrder +60 -1: Lsun/reflect/annotation/TypeAnnotation$TypeAnnotationTarget; +20 -1: META-INF/MANIFEST.MF +18 -1: getSuperInterfaces +26 -1: (Ljava/nio/ByteBuffer;IZ)C +26 -1: (Ljava/nio/ByteBuffer;IZ)D +9 -1: PROTECTED +18 -1: not visible from +26 -1: java/lang/RuntimeException +26 -1: (Ljava/nio/ByteBuffer;IZ)F +20 -1: java/net/FileNameMap +15 -1: insertArguments +8 -1: diagprop +26 -1: (Ljava/nio/ByteBuffer;IZ)I +26 -1: (Ljava/nio/ByteBuffer;IZ)J +20 -1: createContentHandler +11 -1: getProtocol +26 -1: (Ljava/nio/ByteBuffer;IZ)S +33 -1: Ljava/lang/NoSuchMethodException; +19 -1: entry name too long +40 -1: java/util/jar/JarVerifier$VerifierStream +6 -1: server +7 -1: OCTOBER +26 -1: sun/invoke/util/VerifyType +6 -1: domain +9 -1: getUnsafe +5 -1: ([Z)I +4 -1: cons +42 -1: ()Ljava/lang/ReflectiveOperationException; +4 -1: byte +29 -1: java/util/function/BiConsumer +24 -1: getJavaUtilZipFileAccess +37 -1: ([Ljava/lang/Object;)Ljava/util/List; +27 -1: timeout can not be negative +62 -1: Ljava/util/Map; +16 -1: getOurStackTrace +34 -1: (J)Ljava/lang/ref/Reference<+TT;>; +50 -1: Lsun/reflect/generics/repository/MethodRepository; +20 -1: MIN_BYTE_BUFFER_SIZE +3 -1: buf +13 -1: getAttributes +6 -1: GERMAN +38 -1: java/security/NoSuchAlgorithmException +20 -1: Direct buffer memory +6 -1: (IIZ)V +27 -1: JVMTI_THREAD_STATE_RUNNABLE +26 -1: [Ljava/io/File$PathStatus; +36 -1: (Ljava/util/List;Ljava/lang/Class;)V +13 -1: JarIndex.java +34 -1: java/lang/Character$CharacterCache +8 -1: csIBM857 +10 -1: LineReader +28 -1: Ljava/lang/RuntimeException; +30 -1: ()Ljava/util/Enumeration; +12 -1: getSeparator +124 -1: (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;)Ljava/lang/Object; +97 -1: Ljava/util/Map;>; +21 -1: ConstantCallSite.java +40 -1: sun/util/locale/provider/LocaleResources +101 -1: ;>(Ljava/util/function/Function<-TT;+TU;>;)Ljava/util/Comparator; +4 -1: copy +23 -1: sun/security/util/Debug +10 -1: isAbsolute +34 -1: (Ljava/lang/invoke/MethodHandle;)V +34 -1: (Ljava/lang/invoke/MethodHandle;)Z +48 -1: ()[Ljava/util/concurrent/ConcurrentHashMap$Node; +34 -1: (Lsun/reflect/LangReflectAccess;)V +8 -1: csIBM862 +8 -1: csIBM866 +64 -1: java/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask +39 -1: No java.util.Objects instances for you! +68 -1: (Ljava/util/PrimitiveIterator$OfInt;JI)Ljava/util/Spliterator$OfInt; +19 -1: Illegal class name +24 -1: uncaughtExceptionHandler +12 -1: runFinalizer +23 -1: java/io/FileInputStream +41 -1: (Ljava/lang/Class<*>;Ljava/lang/String;)V +98 -1: (Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node; +30 -1: java/nio/charset/CoderResult$1 +20 -1: SourceDebugExtension +30 -1: java/nio/charset/CoderResult$2 +69 -1: ([Ljava/security/ProtectionDomain;[Ljava/security/ProtectionDomain;)Z +14 -1: 1.8.0-internal +16 -1: ReduceValuesTask +13 -1: toLowerString +14 -1: newPrintStream +13 -1: unicodelittle +19 -1: getClassLoadingLock +9 -1: DigitTens +80 -1: (Ljava/lang/Class<*>;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodType; +12 -1: sun_eu_greek +21 -1: getBootstrapClassPath +9 -1: volatile +15 -1: UnmodifiableMap +21 -1: enumConstantDirectory +10 -1: getContent +4 -1: cosh +74 -1: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale; +11 -1: ([JII[JII)V +28 -1: java/lang/reflect/Executable +17 -1: MapReduceKeysTask +6 -1: isOpen +17 -1: AnnotationDefault +17 -1: Already connected +27 -1: (Lsun/misc/JavaNetAccess;)V +34 -1: ([BILjava/nio/charset/Charset;Z)[B +55 -1: Ljava/lang/invoke/DirectMethodHandle$EnsureInitialized; +8 -1: Set.java +10 -1: DEAD_ENTRY +7 -1: nextInt +3 -1: wtb +23 -1: java/util/Collections$1 +86 -1: (Lsun/reflect/generics/factory/GenericsFactory;)Lsun/reflect/generics/visitor/Reifier; +23 -1: java/util/Collections$2 +23 -1: java/util/Collections$3 +18 -1: DoubleCumulateTask +22 -1: skip value is negative +85 -1: (Ljava/io/InputStream;Ljava/lang/Object;Ljava/lang/String;)Lsun/nio/cs/StreamDecoder; +5 -1: \\[\\]$ +34 -1: Ljava/util/NoSuchElementException; +3 -1: NaN +30 -1: sun/util/calendar/CalendarDate +10 -1: V_Constant +20 -1: java/lang/Comparable +9 -1: text/html +20 -1: -9223372036854775808 +20 -1: DataInputStream.java +20 -1: Member defaults: +35 -1: Ljava/lang/ref/ReferenceQueue$Lock; +8 -1: getBytes +17 -1: CodePointIterator +11 -1: Signal.java +19 -1: javaHomePrefixCache +12 -1: replaceFirst +37 -1: Ljava/lang/IndexOutOfBoundsException; +39 -1: (Ljava/lang/String;ZI)Ljava/lang/Class; +21 -1: initSystemClassLoader +28 -1: America/Indiana/Indianapolis +47 -1: (Ljava/security/Permission;Ljava/lang/Object;)V +27 -1: java/net/URISyntaxException +21 -1: createSecurityManager +7 -1: suspend +12 -1: L_UNRESERVED +17 -1: checkMemberAccess +12 -1: CoreCounters +19 -1: java/net/HttpCookie +8 -1: isGetter +17 -1: setDaylightSaving +27 -1: java.launcher.javafx.error1 +53 -1: java/util/concurrent/ConcurrentHashMap$CollectionView +16 -1: readUnsignedByte +47 -1: (Ljava/lang/String;)Ljava/net/URLStreamHandler; +40 -1: (Z)[Ljava/lang/reflect/Constructor; +14 -1: javaLangAccess +5 -1: apply +8 -1: getFloat +15 -1: getD3DAvailable +25 -1: startLocalManagementAgent +7 -1: RUNTIME +22 -1: LocalVariableTypeTable +8 -1: doOutput +16 -1: CheckedSortedSet +10 -1: zoneOffset +64 -1: (Ljava/security/Permission;)Ljava/security/PermissionCollection; +13 -1: hasUnresolved +13 -1: user.language +11 -1: getDoubleAt +14 -1: getQueueLength +37 -1: java/nio/DirectByteBuffer$Deallocator +6 -1: ASHIFT +9 -1: checkPath +80 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)V +6 -1: CENEXT +16 -1: doubleToLongBits +11 -1: copyToArray +9 -1: copyField +36 -1: ()Lsun/util/calendar/Gregorian$Date; +53 -1: (ILjava/lang/Object;)Ljava/util/HashMap$Node; +44 -1: (TK;TV;Ljava/lang/ref/ReferenceQueue;)V +35 -1: java/util/Collections$EmptyIterator +38 -1: sealing violation: can't seal package +37 -1: (Ljava/util/Queue;Ljava/lang/Class;)V +129 -1: (Ljava/lang/Class<*>;Ljava/lang/String;[Ljava/lang/Class<*>;Ljava/lang/Class<*>;[Ljava/lang/Class<*>;IILjava/lang/String;[B[B[B)V +18 -1: HashMapSpliterator +8 -1: putShort +23 -1: (Ljava/lang/Object;II)V +7 -1: GERMANY +13 -1: toTitleString +102 -1: (Ljava/util/ArrayPrefixHelpers$CumulateTask;Ljava/util/function/BinaryOperator;[Ljava/lang/Object;II)V +44 -1: ([Ljava/lang/Object;)Ljava/util/Spliterator; +6 -1: unused +25 -1: java/net/URLClassLoader$1 +25 -1: java/net/URLClassLoader$2 +25 -1: java/net/URLClassLoader$3 +25 -1: java/net/URLClassLoader$4 +12 -1: getFixedDate +25 -1: java/net/URLClassLoader$5 +4 -1: time +25 -1: java/net/URLClassLoader$6 +25 -1: java/net/URLClassLoader$7 +14 -1: historicalName +12 -1: normalizeKey +13 -1: MIN_SURROGATE +41 -1: java/nio/charset/CharacterCodingException +18 -1: java/lang/Iterable +8 -1: ([JII)[J +103 -1: Ljava/util/Map;Ljava/lang/annotation/Annotation;>; +18 -1: putBooleanVolatile +5 -1: Entry +11 -1: CounterCell +12 -1: monitorEnter +10 -1: skipBuffer +15 -1: hasMoreElements +24 -1: newIllegalStateException +24 -1: Ljava/lang/LinkageError; +12 -1: getEntryFlag +44 -1: (Ljava/lang/Throwable$PrintStreamOrWriter;)V +18 -1: java/nio/IntBuffer +17 -1: jdk_minor_version +28 -1: DIRECTIONALITY_RIGHT_TO_LEFT +15 -1: getAndSetObject +7 -1: sizeCtl +15 -1: Ljava/util/Set; +32 -1: (I)Ljava/lang/invoke/LambdaForm; +16 -1: runFinalization0 +30 -1: Ljava/lang/reflect/Executable; +15 -1: compareUnsigned +5 -1: nkeys +31 -1: Ljava/nio/channels/FileChannel; +40 -1: sun/reflect/generics/tree/ClassSignature +22 -1: (Ljava/lang/Object;I)B +22 -1: (Ljava/lang/Object;I)C +22 -1: (Ljava/lang/Object;I)D +7 -1: JANUARY +30 -1: newGetIllegalArgumentException +22 -1: (Ljava/lang/Object;I)F +22 -1: (Ljava/lang/Object;I)I +22 -1: (Ljava/lang/Object;I)J +28 -1: generateNamedFunctionInvoker +38 -1: (Ljava/lang/String;)Ljava/time/ZoneId; +19 -1: lambda$codePoints$2 +4 -1: Null +7 -1: setEras +15 -1: lambda$chars$15 +14 -1: CollectionView +24 -1: (C)Ljava/io/PrintStream; +22 -1: (Ljava/lang/Object;I)S +96 -1: (Ljava/security/AccessControlContext;Lsun/security/util/Debug;Ljava/security/ProtectionDomain;)V +17 -1: getJulianCalendar +22 -1: (Ljava/lang/Object;I)V +17 -1: getMethodAccessor +9 -1: not owner +35 -1: java/lang/reflect/ParameterizedType +15 -1: ValueCollection +22 -1: (Ljava/lang/Object;I)Z +4 -1: utf8 +5 -1: CHINA +9 -1: sprintf0d +18 -1: java/nio/file/Path +35 -1: DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC +30 -1: URI has an authority component +43 -1: (Ljava/lang/Object;)Ljava/util/Spliterator; +15 -1: +62 -1: (Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale; +6 -1: ([ZZ)V +10 -1: getContext +12 -1: content-type +99 -1: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;ILjava/util/WeakHashMap$Entry;)V +51 -1: (Ljava/util/concurrent/ConcurrentHashMap;)V +27 -1: Invalid constant pool index +20 -1: getUnicodeLocaleType +43 -1: Ljava/nio/charset/CharacterCodingException; +113 -1: (Ljava/net/URL;Ljava/net/URLStreamHandler;Ljava/util/HashMap;)V +56 -1: (Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale; +24 -1: Lsun/misc/SignalHandler; +8 -1: readlink +125 -1: (Ljava/nio/file/WatchService;[Ljava/nio/file/WatchEvent$Kind<*>;[Ljava/nio/file/WatchEvent$Modifier;)Ljava/nio/file/WatchKey; +11 -1: initStatics +15 -1: unmappableCache +13 -1: fixMethodType +25 -1: sun/net/www/MessageHeader +3 -1: cdt +27 -1: Ljava/util/Locale$Category; +59 -1: (ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object; +8 -1: Accessor +14 -1: mapLibraryName +54 -1: (Lsun/misc/URLClassPath$JarLoader;)Lsun/misc/JarIndex; +24 -1: ZoneOffsetTransitionRule +7 -1: getChar +3 -1: cee +25 -1: MapReduceValuesToLongTask +20 -1: declaredPublicFields +44 -1: (Ljava/lang/ClassLoader;Ljava/lang/String;)J +13 -1: removeElement +20 -1: Ljava/nio/ByteOrder; +8 -1: parallel +67 -1: (Ljava/lang/reflect/Constructor;Lsun/reflect/ConstructorAccessor;)V +22 -1: java/util/zip/ZipCoder +8 -1: ([ZIIZ)V +45 -1: (Ljava/lang/String;Ljava/lang/CharSequence;)Z +8 -1: february +40 -1: java/util/zip/ZipFile$ZipFileInputStream +47 -1: java/nio/charset/Charset$ExtendedProviderHolder +13 -1: IEEEremainder +15 -1: sun/misc/Perf$1 +9 -1: abstract +20 -1: ()Ljava/time/ZoneId; +7 -1: ONE_DAY +92 -1: (Ljava/util/concurrent/ConcurrentHashMap$Node;)Ljava/util/concurrent/ConcurrentHashMap$Node; +45 -1: (Ljava/util/ListIterator;I)Ljava/lang/Object; +16 -1: Buffer size <= 0 +9 -1: checkName +11 -1: getJarEntry +20 -1: Replacement too long +53 -1: (Ljava/lang/String;)Ljava/nio/charset/CharsetDecoder; +12 -1: isWhitespace +15 -1: csISOLatinGreek +70 -1: (Ljava/lang/reflect/Constructor<*>;Lsun/reflect/ConstructorAccessor;)V +20 -1: TypeAnnotationTarget +3 -1: No +27 -1: Lsun/reflect/FieldAccessor; +12 -1: doPrivileged +83 -1: (JLjava/util/function/ToIntFunction<-TV;>;ILjava/util/function/IntBinaryOperator;)I +60 -1: (Ljava/nio/file/attribute/FileTime;)Ljava/util/zip/ZipEntry; +11 -1: changeEntry +18 -1: MessageHeader.java +51 -1: ([Ljava/lang/String;Ljava/util/Map;)Ljava/util/Map; +9 -1: castEntry +16 -1: ACCESS_MODIFIERS +11 -1: newInstance +24 -1: lastIndexOfSupplementary +13 -1: JZENTRY_EXTRA +5 -1: LONGS +7 -1: domain +16 -1: protocolPathProp +21 -1: java/util/Hashtable$1 +10 -1: isSameDate +23 -1: (I)Ljava/nio/file/Path; +33 -1: java/util/PrimitiveIterator$OfInt +7 -1: ([II)[I +8 -1: variant= +29 -1: (Ljava/util/Collection<*>;Z)Z +38 -1: already loaded in another classloader +10 -1: setSeconds +9 -1: makeShort +59 -1: ClassLoader.findLibrary failed to return an absolute path: +26 -1: java/util/jar/JarException +9 -1: setCharAt +13 -1: initCauseFrom +13 -1: val$fieldName +18 -1: MIN_HIGH_SURROGATE +60 -1: (Lsun/util/calendar/ZoneInfoFile$ZoneOffsetTransitionRule;)B +25 -1: getDayOfWeekFromFixedDate +10 -1: maybeReBox +9 -1: getHandle +60 -1: (Lsun/util/calendar/ZoneInfoFile$ZoneOffsetTransitionRule;)I +59 -1: ([Ljava/lang/Class<*>;)Ljava/lang/reflect/Constructor; +3 -1: cis +11 -1: getIssuerDN +9 -1: codebase= +80 -1: (ILjava/lang/invoke/BoundMethodHandle$SpeciesData;)Ljava/lang/invoke/LambdaForm; +29 -1: addThreadDumpForSynchronizers +6 -1: FRANCE +77 -1: ([TU;ILjava/lang/Class<+[TT;>;)[TT; +45 -1: ()Ljava/util/List; +16 -1: putFloatVolatile +34 -1: (Ljava/lang/Class;)Ljava/util/Map; +28 -1: ()Ljava/security/Permission; +28 -1: (Ljava/lang/CharSequence;I)I +51 -1: ()Ljava/util/Enumeration; +25 -1: (II)Ljava/nio/ByteBuffer; +20 -1: BasicPermission.java +5 -1: isNaN +48 -1: (Ljava/lang/Throwable;)Ljava/lang/InternalError; +10 -1: ONE_MINUTE +55 -1: (Ljava/lang/invoke/DirectMethodHandle$StaticAccessor;)J +13 -1: DAYS_IN_MONTH +7 -1: domains +10 -1: isUnshared +58 -1: Ljava/lang/Number;Ljava/lang/Comparable; +47 -1: (Ljava/util/List;)Ljava/security/cert/CertPath; +28 -1: ()Ljava/util/Enumeration<*>; +34 -1: sun/misc/Launcher$ExtClassLoader$1 +22 -1: (CLjava/lang/Object;)Z +64 -1: Ljava/lang/ref/WeakReference; +7 -1: ENGLISH +27 -1: (Ljava/util/zip/Inflater;)V +24 -1: makeArrayElementAccessor +72 -1: (Ljava/lang/Class<*>;[Ljava/lang/Class<*>;)Ljava/lang/invoke/MethodType; +48 -1: (Ljava/util/jar/JarFile;)Ljava/util/Enumeration; +48 -1: (Ljava/lang/Class;)Ljava/lang/invoke/MethodType; +15 -1: getNthDayOfWeek +16 -1: printHelpMessage +15 -1: getAbsoluteFile +9 -1: OPEN_READ +19 -1: willGMTOffsetChange +28 -1: (Ljava/util/LinkedHashMap;)V +37 -1: java/security/AllPermissionCollection +5 -1: [id=" +34 -1: java/lang/invoke/BoundMethodHandle +31 -1: ()Ljava/security/cert/CertPath; +50 -1: java/util/ArraysParallelSortHelpers$FJShort$Sorter +14 -1: StaticAccessor +22 -1: synchronizedCollection +53 -1: ([Ljava/io/File;)Ljava/security/AccessControlContext; +37 -1: (Ljava/lang/Class;Ljava/lang/Class;)Z +14 -1: codePointCount +13 -1: is param at +37 -1: Ljava/lang/invoke/MemberName$Factory; +20 -1: annotationDataOffset +31 -1: protocol doesn't support output +11 -1: hostAddress +12 -1: ,dstSavings= +35 -1: java.lang.Integer.IntegerCache.high +15 -1: ParallelLoaders +48 -1: (Ljava/util/Locale;)Lsun/util/locale/BaseLocale; +8 -1: getSize0 +22 -1: checkCreateClassLoader +8 -1: transfer +32 -1: (Lsun/misc/JavaSecurityAccess;)V +26 -1: ()Ljava/net/URLConnection; +3 -1: cmp +9 -1: setMillis +34 -1: sun/util/calendar/AbstractCalendar +19 -1: getDirectBufferPool +7 -1: ([FII)V +28 -1: ([C)Ljava/lang/StringBuffer; +54 -1: (Ljava/lang/Class<*>;)Ljava/security/ProtectionDomain; +26 -1: (Ljava/nio/ByteBuffer;IF)V +11 -1: discardMark +71 -1: (Ljava/lang/Class;)Lsun/util/locale/provider/LocaleServiceProviderPool; +30 -1: java/io/UTFDataFormatException +53 -1: (Ljava/nio/CharBuffer;)Ljava/nio/charset/CoderResult; +48 -1: java/util/concurrent/ConcurrentHashMap$Traverser +5 -1: ([F)I +37 -1: (IC)Ljava/lang/AbstractStringBuilder; +27 -1: Ljava/util/jar/JarVerifier; +22 -1: java/util/Spliterators +32 -1: java/lang/invoke/MutableCallSite +20 -1: java/io/Serializable +5 -1: ([F)V +35 -1: (Ljava/security/ProtectionDomain;)V +33 -1: ()Ljava/lang/ref/Reference<+TT;>; +10 -1: unlinkLast +6 -1: (JSZ)V +8 -1: isStatic +14 -1: subclassAudits +23 -1: (Ljava/lang/String;)TT; +17 -1: java.awt.headless +9 -1: +39 -1: Lsun/util/locale/LocaleSyntaxException; +8 -1: location +3 -1: cos +27 -1: createGarbageCollectorMBean +20 -1: MAX_MH_INVOKER_ARITY +75 -1: (Ljava/nio/ByteBuffer;Ljava/nio/CharBuffer;Z)Ljava/nio/charset/CoderResult; +14 -1: Cloneable.java +50 -1: (Lsun/reflect/DelegatingConstructorAccessorImpl;)V +26 -1: sun/nio/ch/FileChannelImpl +51 -1: (Ljava/lang/Class;Ljava/lang/reflect/Constructor;)V +18 -1: Unknown byte order +28 -1: ()[Lsun/invoke/util/Wrapper; +21 -1: getReadClassBytesTime +64 -1: (Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodTypeForm; +11 -1: setDelegate +20 -1: (Ljava/util/List;)[C +7 -1: usemmap +22 -1: (CC)Ljava/lang/String; +34 -1: sun/invoke/util/BytecodeDescriptor +21 -1: getJavaSecurityAccess +53 -1: (Ljava/nio/ByteBuffer;)Ljava/nio/charset/CoderResult; +7 -1: ibm-737 +19 -1: (Ljava/lang/Enum;)I +4 -1: rint +11 -1: Constructor +9 -1: arraycopy +35 -1: ([D)Ljava/util/stream/DoubleStream; +13 -1: comparingLong +40 -1: Ljava/lang/Object; +23 -1: OutputStreamWriter.java +8 -1: getShort +17 -1: CLASSPATH_LASTOCC +13 -1: createNewFile +14 -1: internalValues +34 -1: Ljava/lang/IllegalAccessException; +23 -1: (JILjava/lang/Object;)V +27 -1: sun.misc.URLClassPath.debug +45 -1: [Ljava/lang/ThreadLocal$ThreadLocalMap$Entry; +35 -1: ()Lsun/reflect/ConstructorAccessor; +12 -1: classEnabled +23 -1: cachedFixedDateNextJan1 +48 -1: (Ljava/util/Locale$LocaleKey;)Ljava/util/Locale; +26 -1: (Ljava/lang/ThreadGroup;)V +7 -1: setErr0 +6 -1: CENFLG +26 -1: (Ljava/lang/ThreadGroup;)Z +18 -1: sun/misc/MetaIndex +3 -1: crc +34 -1: (Z)Ljava/lang/invoke/MethodHandle; +12 -1: replaceNames +15 -1: java/util/Stack +57 -1: Ljava/util/Vector; +89 -1: (JLjava/util/function/ToDoubleFunction<-TV;>;DLjava/util/function/DoubleBinaryOperator;)D +24 -1: permission can't be null +22 -1: Unable to connect to: +44 -1: (Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer; +14 -1: floatToIntBits +11 -1: getLastRule +6 -1: EXTCRC +26 -1: java/net/InetSocketAddress +36 -1: (Lsun/misc/URLClassPath$JarLoader;)V +27 3: sun/launcher/LauncherHelper +8 -1: ecma-118 +49 -1: (Ljava/net/URL;Ljava/lang/String;)[Ljava/net/URL; +13 -1: hashCodeValue +5 -1: CESU8 +21 -1: appendVmSelectMessage +13 -1: bindImmediate +12 -1: closeLoaders +16 -1: emptySpliterator +28 -1: (J)Ljava/time/LocalDateTime; +22 -1: [Ljava/lang/Character; +5 -1: certs +6 -1: (null) +25 -1: java/io/ObjectInputStream +27 -1: ([Ljava/lang/ThreadGroup;)I +3 -1: cst +3 -1: csu +20 -1: java/nio/ShortBuffer +53 -1: (Ljava/lang/ClassValue;Ljava/lang/ClassValue$Entry;)V +4 -1: (Z)I +24 -1: Ljava/io/FileDescriptor; +6 -1: cclass +10 -1: , profile +39 -1: (Ljava/lang/String;)Ljava/lang/Process; +4 -1: (Z)V +5 -1: toURI +24 -1: ConstructorAccessor.java +5 -1: toURL +18 -1: addAllIfNotPresent +4 -1: (Z)Z +5 -1: parse +11 -1: isPrimitive +42 -1: (Ljava/io/File;)Ljava/lang/ProcessBuilder; +36 -1: (Ljava/util/Date;)Ljava/lang/String; +23 -1: getFormalTypeParameters +13 -1: Resource.java +7 -1: ibm-775 +6 -1: isEnum +24 -1: setJavaUtilZipFileAccess +21 -1: \t[CIRCULAR REFERENCE: +51 -1: (Ljava/lang/CharSequence;)Ljava/util/regex/Matcher; +24 -1: (I)Ljava/nio/ByteBuffer; +53 -1: sun/reflect/generics/repository/GenericDeclRepository +3 -1: xor +17 -1: invokeBasicMethod +27 -1: java/lang/invoke/LambdaForm +99 -1: (Ljava/util/jar/Manifest;Ljava/util/jar/JarEntry;Ljava/io/InputStream;Ljava/util/jar/JarVerifier;)V +46 -1: Lsun/reflect/generics/factory/GenericsFactory; +37 -1: sun/misc/Launcher$BootClassPathHolder +10 -1: BindCaller +24 -1: java/lang/reflect/Member +32 -1: java/lang/management/ThreadState +5 -1: (IB)V +21 -1: RuntimeException.java +5 -1: ended +17 -1: java/util/TreeSet +7 -1: : no !/ +16 -1: java/util/Vector +9 -1: nextAfter +22 -1: Ljava/lang/Deprecated; +20 -1: requestedCharsetName +37 -1: ([JIII)Ljava/util/Spliterator$OfLong; +14 -1: internArgument +11 -1: getTimeZone +10 -1: isValidKey +11 -1: LAST_RESULT +43 -1: sun/reflect/annotation/TypeAnnotationParser +13 -1: encodedInPath +52 -1: (Ljava/security/PrivilegedAction;)Ljava/lang/Object; +4 -1: LL_L +34 -1: java/nio/charset/CodingErrorAction +10 -1: copyFields +11 -1: getConstant +9 -1: threshold +13 -1: aliases_UTF_8 +27 -1: (Ljava/util/ArrayDeque;II)V +29 -1: Ljava/lang/ref/SoftReference; +19 -1: indexedBinarySearch +11 -1: containsKey +81 -1: ([Ljava/lang/ClassValue$Entry;Ljava/lang/ClassValue;)Ljava/lang/ClassValue$Entry; +86 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/Class<*>;II)Ljava/lang/invoke/MethodHandle; +15 -1: cannot convert +25 -1: getSystemResourceAsStream +46 -1: (Ljava/util/Properties;)Ljava/util/Properties; +12 -1: reverseOrder +16 -1: getSystemPackage +8 -1: ([SII)[S +19 -1: makeAccessException +100 -1: (JLjava/util/function/Function<-TK;+TU;>;Ljava/util/function/Consumer<-TU;>;)V +39 -1: ([Ljava/lang/Class;I)[Ljava/lang/Class; +19 -1: Ljava/lang/Boolean; +6 -1: Hidden +47 -1: java/lang/invoke/MethodHandleImpl$ArrayAccessor +5 -1: APRIL +8 -1: emptySet +11 -1: getCombiner +58 -1: (Ljava/lang/String;I[Ljava/lang/invoke/LambdaForm$Name;I)V +24 -1: java.system.class.loader +14 -1: Can't handle: +16 -1: isNullConversion +38 -1: ()Ljava/util/HashMap$TreeNode; +29 -1: referenceKindIsConsistentWith +11 -1: flushBuffer +8 -1: putField +27 -1: ()Ljava/security/PublicKey; +53 -1: ()Ljava/util/stream/Stream; +10 -1: pathToURLs +26 -1: throwIllegalStateException +10 -1: markedChar +14 -1: isNativeMethod +36 -1: (I)Ljava/lang/AbstractStringBuilder; +54 -1: java/util/concurrent/ConcurrentHashMap$ReservationNode +45 -1: Lsun/misc/JavaSecurityProtectionDomainAccess; +62 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;Ljava/lang/Object;I)V +7 -1: subList +8 -1: UTF_32BE +6 -1: U_None +50 -1: sun/reflect/generics/repository/AbstractRepository +62 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;Ljava/lang/Object;I)Z +43 -1: sun/net/www/protocol/file/FileURLConnection +13 -1: setZoneOffset +43 -1: Underlying input stream returned zero bytes +54 -1: [a-zA-Z_$][a-zA-Z0-9_$]*([.][a-zA-Z_$][a-zA-Z0-9_$]*)* +13 -1: containsValue +44 -1: (Ljava/nio/CharBuffer;)Ljava/nio/ByteBuffer; +25 -1: isNullReferenceConversion +38 -1: Ljava/util/Vector; +6 -1: toFile +7 -1: getSlot +17 -1: (Ljava/net/URI;)V +32 -1: java.security.cert.Certificate: +24 -1: ()Lsun/misc/PerfCounter; +11 -1: Asia/Hebron +16 -1: createMemoryPool +10 -1: addToCache +29 -1: Ljava/lang/invoke/DontInline; +39 -1: java/lang/ref/Finalizer$FinalizerThread +58 -1: (Ljava/lang/Class;)Lsun/reflect/generics/scope/ClassScope; +20 -1: getBooleanAttributes +15 -1: parallelLockMap +34 -1: java/util/Vector$VectorSpliterator +21 -1: createMemoryPoolMBean +15 -1: no content-type +41 -1: Couldn't find 3-letter language code for +5 -1: slash +34 -1: Ljava/lang/annotation/ElementType; +8 -1: isSetter +26 -1: (ZLjava/lang/String;JJJZ)V +6 -1: GMT_ID +73 -1: ()[Ljava/lang/reflect/TypeVariable;>; +56 -1: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; +32 -1: (Ljava/util/Set;)Ljava/util/Set; +4 -1: stop +62 -1: (Ljava/lang/String;IILjava/lang/String;I)Ljava/nio/ByteBuffer; +11 -1: genericInfo +11 -1: listToArray +26 -1: ()Ljava/util/jar/Manifest; +13 -1: putOrderedInt +5 -1: flush +13 -1: ArrayAccessor +4 -1: Name +95 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;[Ljava/util/concurrent/ConcurrentHashMap$Node;)V +68 -1: (Ljava/lang/Class;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; +23 -1: java/lang/ref/Reference +37 -1: (Ljava/nio/file/attribute/FileTime;)J +14 -1: MIN_CODE_POINT +9 -1: ISO8859-1 +9 -1: ISO8859-2 +9 -1: ISO8859-5 +34 -1: ([CILjava/nio/charset/Charset;Z)[C +9 -1: ISO8859-9 +9 -1: getUTF8At +12 -1: java/net/URI +67 -1: (Ljava/io/DataInput;Ljava/lang/String;)Lsun/util/calendar/ZoneInfo; +22 -1: ListCompositionPattern +67 -1: (Ljava/lang/String;[BIILjava/security/CodeSource;)Ljava/lang/Class; +3 1: xxx +12 -1: java/net/URL +27 -1: Can't overwrite cause with +30 -1: sun/util/locale/BaseLocale$Key +22 -1: forkSecondaryFinalizer +23 -1: java/security/Principal +8 -1: makeSite +17 -1: NEGATIVE_INFINITY +12 -1: addUnstarted +12 -1: internalForm +9 -1: cellsBusy +23 -1: (Ljava/lang/Object;IJ)V +13 -1: getParameters +6 -1: H_PATH +10 -1: L_REG_NAME +139 -1: Ljava/util/AbstractMap;Ljava/util/Map;Ljava/lang/Cloneable;Ljava/io/Serializable; +6 -1: latin0 +10 -1: addSeconds +6 -1: latin1 +6 -1: latin2 +6 -1: latin4 +6 -1: latin5 +17 -1: getWaitingThreads +6 -1: latin9 +21 -1: java/util/Comparators +10 -1: trimToSize +96 -1: (Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/Collection; +43 -1: ([JLjava/util/function/IntToLongFunction;)V +23 -1: GET_COMBINER_PERMISSION +20 -1: lambda$replaceAll$14 +5 -1: KOREA +20 -1: getJvmSpecialVersion +9 -1: dumpStack +16 -1: CACHE_LOAD_LIMIT +43 -1: GSS LoginConfigImpl debugging +26 -1: (DLjava/lang/Appendable;)V +8 -1: forName0 +35 -1: java/lang/ClassLoader$NativeLibrary +46 -1: java/util/concurrent/ConcurrentHashMap$Segment +24 -1: getDeclaredAnnotationMap +89 -1: java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1 +20 -1: java_runtime_version +26 -1: java/util/stream/IntStream +16 -1: Ljava/io/Writer; +69 -1: ()Ljava/util/SortedMap; +15 -1: getClassLoader0 +6 -1: x86_64 +11 -1: isInterface +15 -1: MODIFIER_SYMBOL +44 -1: Note: Separate multiple options with a comma +9 -1: recursive +19 -1: java/nio/CharBuffer +8 -1: capacity +17 -1: validateMainClass +50 -1: (Ljava/util/Set;Ljava/lang/Object;)Ljava/util/Set; +22 -1: (Ljava/lang/Object;J)B +22 -1: (Ljava/lang/Object;J)C +22 -1: (Ljava/lang/Object;J)D +17 -1: not a method type +22 -1: (Ljava/lang/Object;J)F +5 -1: count +32 -1: AtomicReferenceFieldUpdater.java +22 -1: (Ljava/lang/Object;J)I +14 -1: methodAccessor +22 -1: (Ljava/lang/Object;J)J +7 -1: isError +51 -1: (Ljava/nio/Buffer;II)Ljava/nio/charset/CoderResult; +53 -1: (BZLjava/lang/Class<*>;)Ljava/lang/invoke/LambdaForm; +25 -1: +5 -1: [pos= +14 -1: lambda$chars$1 +9 -1: CELLVALUE +16 -1: haveLeftoverChar +22 -1: ([Ljava/lang/String;)V +32 -1: java/lang/InstantiationException +7 -1: SIG_IGN +13 -1: ZipUtils.java +50 -1: Ljava/lang/ref/ReferenceQueue; +22 -1: (Ljava/lang/Object;J)S +69 -1: Ljava/util/HashMap; +16 -1: newInternalError +22 -1: (Ljava/lang/Object;J)V +9 -1: ABBR_MASK +5 -1: array +22 -1: (Ljava/lang/Object;J)Z +13 -1: FilteringMode +30 -1: java/util/stream/StreamSupport +19 -1: retrieveDisplayName +56 -1: (Ljava/util/TimeZone;)Lsun/util/calendar/Gregorian$Date; +10 -1: val$values +9 -1: normalize +28 -1: (II)Ljava/lang/CharSequence; +16 -1: serialVersionUID +7 -1: getPath +25 -1: (ILjava/lang/Class<*>;Z)V +13 -1: thenComparing +51 -1: (Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; +36 -1: ()[Ljava/lang/annotation/Annotation; +14 -1: MetaIndex.java +8 -1: identity +15 -1: findSystemClass +24 -1: privateGetDeclaredFields +27 -1: java/lang/ref/SoftReference +19 -1: useCanonPrefixCache +3 -1: dec +3 -1: PLT +8 -1: UTF_32LE +17 -1: java/util/HashMap +12 -1: toEpochMilli +9 -1: intStream +11 -1: Caused by: +31 -1: java/nio/charset/CharsetDecoder +30 -1: is being checked +11 -1: parseHeader +25 -1: ACCUMULATED_DAYS_IN_MONTH +34 -1: newGetByteIllegalArgumentException +21 -1: checkPropertiesAccess +13 -1: StackMapTable +8 -1: addCount +51 -1: (Ljava/lang/invoke/MethodHandle;)Ljava/lang/String; +9 -1: authority +15 -1: iso-10646-ucs-2 +6 -1: SUNDAY +22 -1: LocalGregorianCalendar +9 -1: listRoots +32 -1: Lsun/reflect/generics/tree/Tree; +38 -1: [Ljava/util/WeakHashMap$Entry; +11 -1: nativeOrder +5 -1: long0 +5 -1: long1 +5 -1: long2 +5 -1: long3 +17 -1: capacityIncrement +5 -1: long4 +97 -1: (Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName; +31 -1: Ljava/lang/CharacterDataLatin1; +5 -1: long5 +5 -1: long6 +5 -1: long7 +17 -1: reduceValuesToInt +13 -1: package2certs +13 -1: isTypeVisible +30 -1: java/lang/ref/PhantomReference +47 -1: ()Ljava/util/stream/Stream; +9 -1: longValue +3 -1: PNT +10 -1: storeToXML +10 -1: getMethod0 +12 -1: constantZero +7 -1: promise +116 -1: (Ljava/lang/String;Lsun/reflect/generics/factory/GenericsFactory;)Lsun/reflect/generics/repository/MethodRepository; +32 -1: DIRECTIONALITY_SEGMENT_SEPARATOR +9 -1: byteOrder +9 -1: isPromise +4 -1: isOn +6 -1: LOCCRC +10 -1: setDefault +9 -1: setHandle +15 -1: java/nio/Buffer +37 -1: (Ljava/lang/String;I)Ljava/lang/Long; +10 -1: Float.java +12 -1: showSettings +27 -1: (Ljava/io/FileDescriptor;)I +27 -1: (Ljava/io/FileDescriptor;)J +21 -1: java/util/Spliterator +22 -1: CodingErrorAction.java +11 -1: isMalformed +27 -1: java/util/PrimitiveIterator +15 -1: THROW_EXCEPTION +15 -1: copyToCharArray +26 -1: ()Ljava/util/jar/JarEntry; +27 -1: (Ljava/io/FileDescriptor;)V +11 -1: getEncoding +48 -1: (Ljava/lang/ThreadLocal<*>;Ljava/lang/Object;I)V +17 -1: java.runtime.name +28 -1: (Lsun/invoke/util/Wrapper;)Z +20 -1: annotationTypeOffset +27 -1: (J)Ljava/lang/StringBuffer; +15 -1: METHOD_RECEIVER +10 -1: startEntry +29 -1: (I)Ljava/lang/reflect/Member; +7 -1: setOut0 +10 -1: getMethods +26 -1: ()Lsun/misc/JavaNioAccess; +18 -1: linkToTargetMethod +8 -1: INSTANCE +3 -1: dir +41 -1: ([Ljava/net/URL;Ljava/lang/ClassLoader;)V +9 -1: unboxCast +58 -1: (TT;)Lsun/invoke/empty/Empty;^TT; +12 -1: java.version +50 -1: (Ljava/io/InputStream;Ljava/nio/charset/Charset;)V +32 2: sun/net/www/protocol/jar/Handler +20 -1: java/lang/Compiler$1 +9 -1: LongCache +14 -1: FILL_THRESHOLD +22 -1: getRawClassAnnotations +9 -1: (JI[CII)I +13 -1: hasMoreTokens +13 -1: getSuperclass +3 -1: PRC +12 -1: MAX_PRIORITY +14 -1: checkCacheLoad +7 -1: lowMask +8 -1: LM_CLASS +7 -1: initIDs +27 -1: Ljava/util/Collection; +3 -1: yes +3 -1: PRT +91 -1: (Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/LambdaForm; +27 -1: ()Lsun/security/util/Debug; +8 -1: VM start +9 -1: setMemory +7 -1: getName +10 -1: findSignal +19 -1: startsWithLocHeader +37 -1: java/util/Collections$SynchronizedMap +51 -1: (ICLjava/lang/Object;)Ljava/lang/invoke/LambdaForm; +62 -1: (Ljava/util/Locale;)Lsun/util/locale/provider/LocaleResources; +17 -1: lastParameterType +9 -1: NO_PTYPES +116 -1: ([Ljava/lang/ClassValue$Entry<*>;Ljava/lang/ClassValue;)Ljava/lang/ClassValue$Entry; +18 -1: DisplayNamePattern +8 -1: getField +5 -1: flags +3 -1: PST +17 -1: annotationDefault +18 -1: java/nio/ByteOrder +8 -1: highMask +6 -1: ascii7 +29 -1: getGregorianYearFromFixedDate +125 -1: (Ljava/lang/String;[Ljava/lang/invoke/LambdaForm$Name;[Ljava/lang/invoke/LambdaForm$Name;Ljava/lang/invoke/LambdaForm$Name;)V +8 -1: =Lambda( +29 -1: Ljava/util/WeakHashMap$Entry; +18 -1: multiValueIterator +74 -1: Ljava/util/LinkedHashMap; +13 -1: CONV_OP_LIMIT +6 -1: sclSet +81 -1: (Lsun/misc/URLClassPath$JarLoader;Ljava/util/jar/JarFile;)Ljava/util/jar/JarFile; +14 -1: appendFragment +46 -1: java/util/Collections$SynchronizedNavigableMap +36 -1: application/x-java-serialized-object +13 -1: setNativeName +53 -1: java/util/concurrent/ConcurrentHashMap$ForwardingNode +16 -1: setJavaAWTAccess +30 -1: methodHandleInvokeLinkerMethod +15 -1: reduceKeysToInt +20 -1: ensureCapacityHelper +23 -1: createFileURLConnection +12 -1: d3dAvailable +69 -1: (Ljava/lang/Object;Ljava/lang/invoke/MethodHandle;)Ljava/lang/String; +49 -1: java/util/ArraysParallelSortHelpers$FJLong$Sorter +21 -1: explicitCastArguments +24 -1: JAVAFX_LAUNCH_MODE_CLASS +9 -1: invoke_MT +18 -1: ensureMemberAccess +74 -1: (Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;)I +36 -1: java/nio/charset/spi/CharsetProvider +23 -1: (Ljava/lang/String;II)V +14 -1: initProperties +4 -1: (F)F +35 -1: [[Ljava/lang/annotation/Annotation; +4 -1: (F)I +106 -1: Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Comparable;Ljava/lang/CharSequence; +46 -1: java/lang/invoke/BoundMethodHandle$SpeciesData +74 -1: (Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;)Z +24 -1: java.launcher.opt.header +37 -1: ([Ljava/security/ProtectionDomain;Z)V +10 -1: lineBuffer +7 -1: ibm-813 +9 -1: isBuiltin +4 -1: (F)V +7 -1: ibm-819 +9 -1: H_ESCAPED +4 -1: (F)Z +20 -1: suppressedExceptions +12 -1: UTF-32LE-BOM +19 -1: CalendarSystem.java +8 -1: readOnly +81 -1: (JLjava/util/function/Function;Ljava/util/function/BiFunction;)Ljava/lang/Object; +32 -1: sun/misc/Launcher$AppClassLoader +78 -1: Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Comparable; +17 -1: [Ljava/lang/Enum; +41 -1: java/util/Collections$CheckedNavigableSet +8 -1: asSetter +3 -1: dom +41 -1: (I)[Ljava/util/WeakHashMap$Entry; +16 -1: localeExtensions +21 -1: sun/net/www/ParseUtil +21 -1: Ljava/nio/ByteBuffer; +29 -1: java/util/concurrent/TimeUnit +25 -1: java/lang/CharacterData00 +15 -1: sun/misc/Unsafe +28 -1: java/io/ByteArrayInputStream +3 -1: dow +25 -1: java/lang/CharacterData01 +25 -1: java/lang/CharacterData02 +6 -1: STORED +11 -1: isTransient +8 -1: function +16 -1: getCanonicalFile +13 -1: ,useDaylight= +24 -1: domain (context is null) +12 -1: Cleaner.java +17 -1: CalendarDate.java +49 -1: Lsun/reflect/generics/repository/FieldRepository; +14 -1: forInputString +25 -1: java/lang/CharacterData0E +67 -1: (Ljava/lang/Object;Ljava/util/function/Supplier;)Ljava/lang/Object; +19 -1: codePointBeforeImpl +6 -1: script +21 -1: systemNativeLibraries +38 -1: ([Ljava/lang/Class;)Ljava/lang/String; +14 -1: CONTENT_LENGTH +19 -1: HeapCharBuffer.java +22 -1: ExtendedProviderHolder +41 -1: java/lang/invoke/InvokerBytecodeGenerator +12 -1: basicInvoker +26 -1: ([Ljava/lang/Comparable;)V +10 -1: val$tclass +47 -1: (Ljava/lang/Throwable;)Lsun/invoke/empty/Empty; +18 -1: isLegalReplacement +22 -1: spliteratorUnknownSize +15 -1: SynchronizedSet +16 -1: MethodParameters +22 -1: desiredAssertionStatus +29 -1: ()Ljava/util/ArrayDeque; +36 -1: ()Ljava/lang/reflect/Constructor<*>; +66 -1: ()Ljava/util/Map; +58 -1: (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V +50 -1: (Ljava/util/concurrent/CountedCompleter;[J[JIIII)V +14 -1: requireNonNull +21 -1: java/lang/ThreadGroup +95 -1: ([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;)V +76 -1: (Ljava/nio/channels/WritableByteChannel;Ljava/nio/charset/CharsetEncoder;I)V +14 -1: reflectionData +33 -1: Ljava/lang/invoke/MethodTypeForm; +7 -1: tuesday +31 -1: ()Lsun/misc/JavaSecurityAccess; +14 -1: fieldFilterMap +28 -1: ([Ljava/lang/ThreadGroup;Z)I +7 -1: ibm-850 +83 -1: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/management/GarbageCollectorMXBean; +7 -1: ibm-852 +5 -1: cesu8 +14 -1: ForwardingNode +29 -1: (Ljava/nio/ByteBuffer;IIIII)V +7 -1: ibm-855 +12 -1: SingletonSet +16 -1: isOtherUppercase +15 -1: FIELD_UNDEFINED +9 -1: makeEntry +7 -1: ibm-857 +10 -1: extensions +10 -1: longStream +19 -1: getGenericSignature +7 -1: newNode +8 -1: jarNames +25 -1: java/util/jar/JarVerifier +49 -1: ()[Lsun/reflect/generics/tree/ClassTypeSignature; +4 -1: wait +115 -1: (Ljava/lang/String;Lsun/reflect/generics/factory/GenericsFactory;)Lsun/reflect/generics/repository/ClassRepository; +56 -1: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; +65 -1: (Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)V +7 -1: ibm-862 +9 -1: ISO646-US +7 -1: ibm-866 +16 -1: extendedProvider +7 -1: ([C[C)Z +93 -1: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; +8 -1: getHours +21 -1: ()[Ljava/lang/String; +187 -1: (Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;Ljava/util/function/BiFunction;)V +106 -1: Ljava/util/concurrent/locks/ReentrantLock;Ljava/io/Serializable; +24 -1: java/nio/file/FileSystem +14 -1: ForEachKeyTask +13 -1: defaultLocale +20 -1: constructorModifiers +13 -1: asWrapperType +42 -1: (Ljava/lang/String;ZI)Ljava/lang/Class<*>; +17 -1: BaseCalendar.java +76 -1: (Ljava/util/jar/JarFile;Ljava/util/jar/JarEntry;)[Ljava/security/CodeSigner; +14 -1: isSynchronized +27 -1: java/nio/DirectByteBuffer$1 +3 -1: ()B +7 -1: ibm-874 +12 -1: exactInvoker +3 -1: ()C +39 -1: (Ljava/lang/Thread;Ljava/lang/Object;)V +3 -1: ()D +3 -1: ()F +27 -1: [Ljava/lang/reflect/Method; +10 -1: floatValue +3 -1: ()I +3 -1: ()J +18 -1: getLocaleResources +59 -1: java/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask +67 -1: (ILjava/lang/Object;Ljava/lang/Object;Ljava/util/Hashtable$Entry;)V +11 -1: maxPriority +11 -1: getStringAt +60 -1: (Ljava/lang/ClassValue$Version;)Ljava/lang/ClassValue$Entry; +3 -1: ()S +49 -1: (Ljava/lang/String;)Ljava/io/ExpiringCache$Entry; +42 -1: (III)Lsun/util/calendar/BaseCalendar$Date; +82 -1: (Ljava/util/Set;Ljava/lang/Object;)Ljava/util/Set; +62 -1: ([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/util/Map; +3 -1: ()V +24 -1: ()Ljava/nio/ShortBuffer; +29 -1: file descriptor can't be null +3 -1: ()Z +7 -1: matcher +66 -1: (Ljava/lang/reflect/Constructor;)Lsun/reflect/ConstructorAccessor; +7 -1: matches +12 -1: getAuthority +16 -1: java/lang/Object +5 -1: (IC)V +17 -1: EmptyListIterator +8 -1: charsets +8 -1: sameFile +47 -1: (TT;Ljava/util/function/UnaryOperator;)TV; +16 -1: overwrittenEntry +15 -1: reinvokerTarget +11 -1: isUpperCase +5 -1: toUri +9 -1: GMT+00:00 +33 -1: java/util/concurrent/ForkJoinPool +10 -1: parseFloat +53 -1: java/util/concurrent/ConcurrentHashMap$SearchKeysTask +48 -1: (Ljava/lang/Object;Ljava/util/LinkedList$Node;)V +82 -1: (Ljava/lang/Class<*>;Ljava/lang/Class<*>;Ljava/lang/Object;ILjava/lang/Class<*>;)V +15 -1: reduceCacheLoad +76 -1: (Ljava/lang/Class<*>;[Ljava/lang/reflect/Method;)[Ljava/lang/reflect/Method; +20 -1: singletonSpliterator +24 -1: getTransitionEpochSecond +24 -1: MapReduceValuesToIntTask +13 -1: ALLOWED_FLAGS +55 -1: (Ljava/lang/reflect/Field;Z)Lsun/reflect/FieldAccessor; +34 -1: [Ljava/lang/annotation/Annotation; +10 -1: readBuffer +21 -1: Illegal month value: +31 -1: java/security/SecureClassLoader +12 -1: reinitialize +5 -1: limit +4 -1: grow +15 -1: getCreationTime +7 -1: , from +25 -1: (Ljava/lang/ClassValue;)V +13 -1: java.compiler +37 -1: ()Ljava/util/Set; +6 -1: FJChar +16 -1: getFieldAccessor +4 -1: eras +11 -1: isSupported +24 -1: ()Ljava/text/DateFormat; +32 -1: java/util/Collections$CopiesList +32 -1: java/io/NotSerializableException +15 -1: typeAnnotations +27 -1: defaultAllowUserInteraction +57 -1: (Ljava/lang/String;I[Ljava/lang/invoke/LambdaForm$Name;)V +18 -1: checkArgumentTypes +71 -1: (Lsun/util/calendar/BaseCalendar$Date;)Lsun/util/calendar/BaseCalendar; +10 -1: isMirrored +27 -1: (I)Ljava/lang/Thread$State; +26 -1: (Ljava/util/Collection;Z)Z +6 -1: ibm367 +16 -1: isAssignableFrom +7 -1: readUTF +35 -1: Ljava/lang/ref/ReferenceQueue; +56 -1: ([Ljava/util/HashMap$Node;Ljava/util/HashMap$TreeNode;)V +8 -1: MANDATED +18 -1: canonicalizeRegion +11 -1: checkAccept +44 -1: (Ljava/net/Proxy;)Lsun/net/ApplicationProxy; +8 -1: ECMA-118 +22 -1: ReflectPermission.java +4 -1: _put +41 -1: java.lang.invoke.MethodHandle.DEBUG_NAMES +47 -1: java/util/concurrent/ConcurrentHashMap$TreeNode +44 -1: (Ljava/net/URL;[Ljava/security/CodeSigner;)V +5 -1: april +44 -1: ([Ljava/lang/Class<*>;Ljava/lang/Class<*>;)V +150 -1: Ljava/util/concurrent/ConcurrentHashMap$CollectionView;Ljava/util/Set;Ljava/io/Serializable; +91 -1: (ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode; +26 -1: sun/net/util/IPAddressUtil +8 -1: Modifier +9 -1: isVarargs +24 -1: -- listing properties -- +16 -1: hasAllPermission +27 -1: MapReduceMappingsToLongTask +29 -1: sharedGetParameterAnnotations +9 -1: argCounts +11 -1: toLocalTime +89 -1: (Ljava/lang/invoke/LambdaForm;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MemberName; +4 -1: ROOT +20 -1: sun.reflect.noCaches +18 -1: UnicodeBigUnmarked +4 -1: Lazy +35 -1: java/lang/invoke/SimpleMethodHandle +20 -1: (I)Ljava/nio/Buffer; +48 -1: ()Lsun/reflect/generics/tree/ClassTypeSignature; +31 -1: (I[CII)Ljava/lang/StringBuffer; +17 -1: America/Anchorage +7 -1: markpos +9 -1: enumerate +11 -1: parseLocale +24 -1: java.launcher.cls.error1 +46 -1: (ILjava/lang/Object;)Ljava/lang/StringBuilder; +24 -1: java.launcher.cls.error2 +24 -1: java.launcher.cls.error3 +24 -1: java.launcher.cls.error4 +21 -1: java/util/ArrayList$1 +17 -1: getExceptionTypes +24 -1: java.launcher.cls.error5 +30 -1: java/util/Spliterator$OfDouble +10 -1: forDecoder +8 -1: getEntry +10 -1: checkGuard +12 -1: checkInitted +34 -1: Lsun/util/locale/LocaleExtensions; +41 -1: java/util/ArraysParallelSortHelpers$FJInt +10 -1: findStatic +22 -1: setConstructorAccessor +34 -1: Lsun/misc/URLClassPath$FileLoader; +20 -1: not a reinvoker MH: +16 -1: LongCumulateTask +11 -1: checkAccess +14 -1: SearchKeysTask +36 -1: ()[Ljava/lang/reflect/AnnotatedType; +11 -1: initDefault diff --git a/test/hotspot/jtreg/runtime/appcds/FieldAnnotationsTest.java b/test/hotspot/jtreg/runtime/appcds/FieldAnnotationsTest.java new file mode 100644 index 00000000000..88a346ff850 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/FieldAnnotationsTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, 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 Test for field annotations. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/FieldAnnotationsApp.java test-classes/MyAnnotation.java + * @run main FieldAnnotationsTest + */ + +import jdk.test.lib.process.OutputAnalyzer; + +// This is a test for the handling of multi-dimensional Arrays in MetaspaceClosure. +// +// We choose FieldAnnotations because they happen to be implemented as a multi-dimension +// Array (Annotations::_fields_annotations, which is of type Array*>*, +// and is handled by the template class PointerArrayRef in metaspaceClosure.hpp). +// +// Specifically, we are testing the following C code, where _fields_annotations is non-NULL: +// +// void Annotations::metaspace_pointers_do(MetaspaceClosure* it) { +// ... +// it->push(&_fields_annotations); +// +// which will be matched with the function +// +// template void MetaspaceClosure::push(Array** mpp, Writability w = _default) +// +public class FieldAnnotationsTest { + public static void main(String[] args) throws Exception { + String[] ARCHIVE_CLASSES = {"FieldAnnotationsApp", "MyAnnotation"}; + String appJar = JarBuilder.build("FieldAnnotationsTest", ARCHIVE_CLASSES); + + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, ARCHIVE_CLASSES); + TestCommon.checkDump(dumpOutput); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, "FieldAnnotationsApp"); + TestCommon.checkExec(execOutput, "Field annotations are OK."); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/FreeUnusedMetadata.java b/test/hotspot/jtreg/runtime/appcds/FreeUnusedMetadata.java new file mode 100644 index 00000000000..30f167cdf20 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/FreeUnusedMetadata.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2017, 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 Unused metadata created during dump time should be freed from the CDS archive. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules jdk.jartool/sun.tools.jar + * @compile test-classes/MethodNoReturn.jasm test-classes/Hello.java + * @run main FreeUnusedMetadata + */ + +import java.nio.file.Files; +import java.nio.file.Paths; +import jdk.test.lib.process.OutputAnalyzer; + +public class FreeUnusedMetadata { + static byte iconst_1 = 4; + static byte pop = 87; + static byte[] pattern = { // This has the same sequence as in test-classes/MethodNoReturn.jasm + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + pop, + iconst_1, + iconst_1, + iconst_1, + iconst_1, + iconst_1, + iconst_1, + iconst_1, + iconst_1, + pop, + pop, + pop, + pop, + pop, + pop, + pop, + pop + }; + + public static void main(String[] args) throws Exception { + String[] ARCHIVE_CLASSES = {"Hello", "MethodNoReturn"}; + String appJar = JarBuilder.build("FreeUnusedMetadata", ARCHIVE_CLASSES); + + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, ARCHIVE_CLASSES); + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(execOutput, "Hello World"); + + + String archive = TestCommon.getCurrentArchiveName(); + System.out.println("Checking for pattern inside " + archive + "..."); + + byte[] data = Files.readAllBytes(Paths.get(archive)); + int max = data.length - pattern.length; + for (int i=0; i \ + // -C .\ + // --release 9 -C . + // the last line begins with "--release" corresponds to the optional versionArgs. + public static void build(String jarName, File dir, String man, String ...versionArgs) + throws Exception { + ArrayList args = new ArrayList(); + if (man != null) { + args.add("cfm"); + } else { + args.add("cf"); + } + args.add(classDir + File.separator + jarName + ".jar"); + if (man != null) { + args.add(man); + } + args.add("-C"); + args.add(dir.getAbsolutePath()); + args.add("."); + for (String verArg : versionArgs) { + args.add(verArg); + } + createJar(args); + } + + public static String build(String jarName, String ...classNames) + throws Exception { + + return createSimpleJar(classDir, getJarFilePath(jarName), classNames); + } + + public static String build(boolean classesInWorkDir, String jarName, String ...classNames) + throws Exception { + if (classesInWorkDir) { + return createSimpleJar(".", getJarFilePath(jarName), classNames); + } else { + return build(jarName, classNames); + } + } + + + public static String buildWithManifest(String jarName, String manifest, + String jarClassesDir, String ...classNames) throws Exception { + String jarPath = getJarFilePath(jarName); + ArrayList args = new ArrayList(); + args.add("cvfm"); + args.add(jarPath); + args.add(System.getProperty("test.src") + File.separator + "test-classes" + + File.separator + manifest); + addClassArgs(args, jarClassesDir, classNames); + createJar(args); + + return jarPath; + } + + + // Execute: jar uvf $jarFile -C $dir . + static void update(String jarFile, String dir) throws Exception { + String jarExe = JDKToolFinder.getJDKTool("jar"); + + ArrayList args = new ArrayList<>(); + args.add(jarExe); + args.add("uvf"); + args.add(jarFile); + args.add("-C"); + args.add(dir); + args.add("."); + + executeProcess(args.toArray(new String[1])); + } + + + private static String createSimpleJar(String jarclassDir, String jarName, + String[] classNames) throws Exception { + + ArrayList args = new ArrayList(); + args.add("cf"); + args.add(jarName); + addClassArgs(args, jarclassDir, classNames); + createJar(args); + + return jarName; + } + + private static void addClassArgs(ArrayList args, String jarclassDir, + String[] classNames) { + + for (String name : classNames) { + args.add("-C"); + args.add(jarclassDir); + args.add(name + ".class"); + } + } + + private static void createJar(ArrayList args) { + if (DEBUG) printIterable("createJar args: ", args); + + Main jarTool = new Main(System.out, System.err, "jar"); + if (!jarTool.run(args.toArray(new String[1]))) { + throw new RuntimeException("jar operation failed"); + } + } + + // Many AppCDS tests use the same simple "Hello.jar" which contains + // simple Hello.class and does not specify additional attributes. + // For this common use case, use this method to get the jar path. + // The method will check if the jar already exists + // (created by another test or test run), and will create the jar + // if it does not exist + public static String getOrCreateHelloJar() throws Exception { + String jarPath = getJarFilePath("hello"); + + File jarFile = new File(jarPath); + if (jarFile.exists()) { + return jarPath; + } else { + return build("hello", "Hello"); + } + } + + public static void compile(String dstPath, String source, String... extraArgs) throws Exception { + ArrayList args = new ArrayList(); + args.add(JDKToolFinder.getCompileJDKTool("javac")); + args.add("-d"); + args.add(dstPath); + if (extraArgs != null) { + for (String s : extraArgs) { + args.add(s); + } + } + args.add(source); + + if (DEBUG) printIterable("compile args: ", args); + + ProcessBuilder pb = new ProcessBuilder(args); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } + + public static void signJar() throws Exception { + String keyTool = JDKToolFinder.getJDKTool("keytool"); + String jarSigner = JDKToolFinder.getJDKTool("jarsigner"); + String classDir = System.getProperty("test.classes"); + String FS = File.separator; + + executeProcess(keyTool, + "-genkey", "-keystore", "./keystore", "-alias", "mykey", + "-storepass", "abc123", "-keypass", "abc123", + "-dname", "CN=jvmtest") + .shouldHaveExitValue(0); + + executeProcess(jarSigner, + "-keystore", "./keystore", "-storepass", "abc123", "-keypass", + "abc123", "-signedjar", classDir + FS + "signed_hello.jar", + classDir + FS + "hello.jar", "mykey") + .shouldHaveExitValue(0); + } + + private static OutputAnalyzer executeProcess(String... cmds) + throws Exception { + + JarBuilder.printArray("executeProcess: ", cmds); + return ProcessTools.executeProcess(new ProcessBuilder(cmds)); + } + + // diagnostic + public static void printIterable(String msg, Iterable l) { + StringBuilder sum = new StringBuilder(); + for (String s : l) { + sum.append(s).append(' '); + } + System.out.println(msg + sum.toString()); + } + + public static void printArray(String msg, String[] l) { + StringBuilder sum = new StringBuilder(); + for (String s : l) { + sum.append(s).append(' '); + } + System.out.println(msg + sum.toString()); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/JvmtiAddPath.java b/test/hotspot/jtreg/runtime/appcds/JvmtiAddPath.java new file mode 100644 index 00000000000..12d41a2c066 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/JvmtiAddPath.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014, 2017, 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 JvmtiEnv::AddToBootstrapClassLoaderSearch and JvmtiEnv::AddToSystemClassLoaderSearch should disable AppCDS + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @bug 8060592 + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @compile test-classes/Hello.java + * @compile test-classes/JvmtiApp.java + * @run main JvmtiAddPath + */ + +import java.io.File; +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +public class JvmtiAddPath { + static String use_whitebox_jar; + static String[] no_extra_matches = {}; + static String[] check_appcds_enabled = { + "[class,load] ExtraClass source: shared object" + }; + static String[] check_appcds_disabled = { + "[class,load] ExtraClass source: file:" + }; + + static void run(String cp, String... args) throws Exception { + run(no_extra_matches, cp, args); + } + + static void run(String[] extra_matches, String cp, String... args) throws Exception { + String[] opts = {"-cp", cp, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", use_whitebox_jar}; + opts = TestCommon.concat(opts, args); + OutputAnalyzer output = TestCommon.execCommon(opts); + TestCommon.checkExec(output, extra_matches); + } + + public static void main(String[] args) throws Exception { + JarBuilder.build("jvmti_addboot", "Hello"); + JarBuilder.build("jvmti_addapp", "Hello"); + JarBuilder.build("jvmti_app", "JvmtiApp", "ExtraClass"); + JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + + // In all the test cases below, appJar does not contain Hello.class. Instead, we + // append JAR file(s) that contain Hello.class to the boot classpath, the app + // classpath, or both, and verify that Hello.class is loaded by the expected ClassLoader. + String appJar = TestCommon.getTestJar("jvmti_app.jar"); // contains JvmtiApp.class + String addappJar = TestCommon.getTestJar("jvmti_addapp.jar"); // contains Hello.class + String addbootJar = TestCommon.getTestJar("jvmti_addboot.jar"); // contains Hello.class + String twoAppJars = appJar + File.pathSeparator + addappJar; + String wbJar = TestCommon.getTestJar("WhiteBox.jar"); + use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + TestCommon.testDump(appJar, TestCommon.list("JvmtiApp", "ExtraClass"), use_whitebox_jar); + + System.out.println("Test case 1: not adding any paths - Hello.class should not be found"); + run(check_appcds_enabled, appJar, "-Xlog:class+load", "JvmtiApp", "noadd"); // appcds should be enabled + + System.out.println("Test case 2: add to boot classpath only - should find Hello.class in boot loader"); + run(check_appcds_disabled, appJar, "-Xlog:class+load", "JvmtiApp", "bootonly", addbootJar); // appcds should be disabled + + System.out.println("Test case 3: add to app classpath only - should find Hello.class in app loader"); + run(appJar, "JvmtiApp", "apponly", addappJar); + + System.out.println("Test case 4: add to boot and app paths - should find Hello.class in boot loader"); + run(appJar, "JvmtiApp", "appandboot", addbootJar, addappJar); + + System.out.println("Test case 5: add to app using -cp, but add to boot using JVMTI - should find Hello.class in boot loader"); + run(twoAppJars, "JvmtiApp", "bootonly", addappJar); + + System.out.println("Test case 6: add to app using AppCDS, but add to boot using JVMTI - should find Hello.class in boot loader"); + TestCommon.testDump(twoAppJars, TestCommon.list("JvmtiApp", "ExtraClass", "Hello"), use_whitebox_jar); + run(twoAppJars, "JvmtiApp", "bootonly", addappJar); + + System.out.println("Test case 7: add to app using AppCDS, no JVMTI calls - should find Hello.class in app loader"); + run(twoAppJars, "JvmtiApp", "noadd-appcds"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/MismatchedUseAppCDS.java b/test/hotspot/jtreg/runtime/appcds/MismatchedUseAppCDS.java new file mode 100644 index 00000000000..085e79e622d --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/MismatchedUseAppCDS.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @summary Try different combination of mismatched UseAppCDS between dump time and run time. + * (Note: AppCDS does not support uncompressed oops.) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/CheckIfShared.java + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main MismatchedUseAppCDS + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class MismatchedUseAppCDS { + public static void main(String[] args) throws Exception { + String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + String appJar = JarBuilder.build("MismatchedUseAppCDS", "CheckIfShared"); + + OutputAnalyzer output; + + // (1): dump with -XX:+UseAppCDS, but run with -XX:-UseAppCDS + TestCommon.testDump(appJar, TestCommon.list("CheckIfShared"), + // command-line arguments ... + "-XX:+UseAppCDS", + use_whitebox_jar); + + output = TestCommon.exec(appJar, + // command-line arguments ... + use_whitebox_jar, + "-XX:-UseAppCDS", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckIfShared", "false"); + TestCommon.checkExec(output); + + // (2): dump with -XX:-UseAppCDS, but run with -XX:+UseAppCDS + TestCommon.testDump(appJar, TestCommon.list("CheckIfShared"), + // command-line arguments ... + "-XX:-UseAppCDS", + use_whitebox_jar); + + output = TestCommon.exec(appJar, + // command-line arguments ... + use_whitebox_jar, + "-XX:+UseAppCDS", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckIfShared", "false"); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/MissingSuperTest.java b/test/hotspot/jtreg/runtime/appcds/MissingSuperTest.java new file mode 100644 index 00000000000..fa9bfb93493 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/MissingSuperTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 2017, 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 When super class is missing during dumping, no crash should happen. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/MissingSuper.java + * @run main MissingSuperTest + */ + +public class MissingSuperTest { + + public static void main(String[] args) throws Exception { + // The classes "MissingSuperSup" and "MissingSuperIntf" are intentionally not + // included into the jar to provoke the test condition + JarBuilder.build("missing_super", "MissingSuper", + "MissingSuperSub", "MissingSuperImpl"); + + String appJar = TestCommon.getTestJar("missing_super.jar"); + TestCommon.test(appJar, TestCommon.list("MissingSuper", + "MissingSuperSub", + "MissingSuperImpl"), + "MissingSuper"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/MultiProcessSharing.java b/test/hotspot/jtreg/runtime/appcds/MultiProcessSharing.java new file mode 100644 index 00000000000..25861868344 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/MultiProcessSharing.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015, 2017, 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 multiple processes with the same archive, ensure they share + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @compile test-classes/MultiProcClass.java + * @run main MultiProcessSharing + */ + +import java.io.File; +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + + +public class MultiProcessSharing { + static String useWbJar; + static String sharedClass1Jar; + static boolean checkPmap = false; + + public static void main(String[] args) throws Exception { + String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + useWbJar = "-Xbootclasspath/a:" + wbJar; + sharedClass1Jar = JarBuilder.build("shared_class1", "MultiProcClass"); + + // create an archive + OutputAnalyzer out = TestCommon.dump(sharedClass1Jar, + TestCommon.list("MultiProcClass"), useWbJar); + TestCommon.checkDump(out); + + // determine whether OK to use pmap for extra test verification + long myPid = ProcessHandle.current().pid(); + checkPmap = (Platform.isLinux() && (MultiProcClass.runPmap(myPid, false) == 0)); + System.out.println("MultiProcessSharing: checkPmap is " + checkPmap); + + // use an archive in several processes concurrently + int numProcesses = 3; + Thread[] threads = new Thread[numProcesses]; + ProcessHandler[] processHandlers = new ProcessHandler[numProcesses]; + for (int i = 0; i < numProcesses; i++) { + processHandlers[i] = new ProcessHandler(i); + threads[i] = new Thread(processHandlers[i]); + } + + for (Thread t : threads) { + t.start(); + } + + for (Thread t : threads) { + try { + t.join(); + } catch (InterruptedException ie) { + throw ie; + } + } + + // check results + for (ProcessHandler ph : processHandlers) { + TestCommon.checkExec(ph.out); + if (checkPmap && !TestCommon.isUnableToMap(ph.out)) { + checkPmapOutput(ph.out.getOutput()); + } + } + } + + + static class ProcessHandler implements Runnable { + int processNumber; + OutputAnalyzer out; + + ProcessHandler(int processNumber) { + this.processNumber = processNumber; + } + + @Override + public void run() { + try { + out = TestCommon.exec(sharedClass1Jar, + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", useWbJar, + "MultiProcClass", "" + processNumber, "" + checkPmap); + } catch (Exception e) { + throw new RuntimeException("Error occurred when using archive, exec()" + e); + } + } + } + + + private static void checkPmapOutput(String stdio) { + System.out.println("Checking pmap output ..."); + String[] lines = stdio.split("\n"); + + boolean foundJsa = false; + boolean foundReadOnlyJsaSection = false; + + for (String line : lines) { + if (line.contains(TestCommon.getCurrentArchiveName())) + System.out.println(line); + foundJsa = true; + if (line.contains("r--")) { + foundReadOnlyJsaSection = true; + } + + // On certain ARM platforms system maps r/o memory mapped files + // as r/x; see JDK-8145694 for details + if ( (Platform.isARM() || Platform.isAArch64()) && line.contains("r-x") ) { + foundReadOnlyJsaSection = true; + } + } + + Asserts.assertTrue(foundJsa && foundReadOnlyJsaSection); + } + +} diff --git a/test/hotspot/jtreg/runtime/appcds/MultiReleaseJars.java b/test/hotspot/jtreg/runtime/appcds/MultiReleaseJars.java new file mode 100644 index 00000000000..fdc6ef06492 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/MultiReleaseJars.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2016, 2017, 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 MultiReleaseJars + * @bug 8170105 + * @summary Test multi-release jar with AppCDS. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @run main/othervm MultiReleaseJars + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.io.IOException; +import jdk.test.lib.process.OutputAnalyzer; + +public class MultiReleaseJars { + + static final int MAJOR_VERSION = Runtime.version().major(); + static final String MAJOR_VERSION_STRING = String.valueOf(Runtime.version().major()); + + static String[] getMain() { + String[] sts = { + "package version;", + "public class Main {", + " public static void main(String[] args) {", + " Version version = new Version();", + " System.out.println(\"I am running on version \" + version.getVersion());", + " }", + "}" + }; + return sts; + } + + static String[] getVersion(int version) { + String[] sts = { + "package version;", + "public class Version {", + " public int getVersion(){ return " + version + "; }", + "}" + }; + return sts; + } + + static void writeFile(File file, String... contents) throws Exception { + if (contents == null) { + throw new java.lang.RuntimeException("No input for writing to file" + file); + } + FileOutputStream fos = new FileOutputStream(file); + PrintStream ps = new PrintStream(fos); + for (String str : contents) { + ps.println(str); + } + ps.close(); + fos.close(); + } + + /* version.jar entries and files: + * META-INF/ + * META-INF/MANIFEST.MF + * version/ + * version/Main.class + * version/Version.class + * META-INF/versions/ + * META-INF/versions// + * META-INF/versions//version/ + * META-INF/versions//version/Version.class + */ + static void createClassFilesAndJar() throws Exception { + String tempDir = System.getProperty("test.classes"); + File baseDir = new File(tempDir + File.separator + "base"); + File vDir = new File(tempDir + File.separator + MAJOR_VERSION_STRING); + + baseDir.mkdirs(); + vDir.mkdirs(); + + File fileMain = TestCommon.getOutputSourceFile("Main.java"); + writeFile(fileMain, getMain()); + + File fileVersion = TestCommon.getOutputSourceFile("Version.java"); + writeFile(fileVersion, getVersion(7)); + JarBuilder.compile(baseDir.getAbsolutePath(), fileVersion.getAbsolutePath(), "--release", "7"); + JarBuilder.compile(baseDir.getAbsolutePath(), fileMain.getAbsolutePath(), + "-cp", baseDir.getAbsolutePath(), "--release", MAJOR_VERSION_STRING); + + String[] meta = { + "Multi-Release: true", + "Main-Class: version.Main" + }; + File metainf = new File(tempDir, "mf.txt"); + writeFile(metainf, meta); + + fileVersion = TestCommon.getOutputSourceFile("Version.java"); + writeFile(fileVersion, getVersion(MAJOR_VERSION)); + JarBuilder.compile(vDir.getAbsolutePath(), fileVersion.getAbsolutePath(), "--release", MAJOR_VERSION_STRING); + + JarBuilder.build("version", baseDir, metainf.getAbsolutePath(), + "--release", MAJOR_VERSION_STRING, "-C", vDir.getAbsolutePath(), "."); + + // the following jar file is for testing case-insensitive "Multi-Release" + // attibute name + String[] meta2 = { + "multi-Release: true", + "Main-Class: version.Main" + }; + metainf = new File(tempDir, "mf2.txt"); + writeFile(metainf, meta2); + JarBuilder.build("version2", baseDir, metainf.getAbsolutePath(), + "--release", MAJOR_VERSION_STRING, "-C", vDir.getAbsolutePath(), "."); + } + + static void checkExecOutput(OutputAnalyzer output, String expectedOutput) throws Exception { + try { + TestCommon.checkExec(output, expectedOutput); + } catch (java.lang.RuntimeException re) { + String cause = re.getMessage(); + if (!expectedOutput.equals(cause)) { + throw re; + } + } + } + + public static void main(String... args) throws Exception { + // create version.jar which contains Main.class and Version.class. + // Version.class has two versions: 8 and the current version. + createClassFilesAndJar(); + + String mainClass = "version.Main"; + String loadInfo = "[class,load] version.Version source: shared objects file"; + String appClasses[] = {"version/Main", "version/Version"}; + String appJar = TestCommon.getTestJar("version.jar"); + String appJar2 = TestCommon.getTestJar("version2.jar"); + String verboseMode = "-verbose:class"; + String enableMultiRelease = "-Djdk.util.jar.enableMultiRelease=true"; + String jarVersion = null; + String expectedOutput = null; + + // 1. default to highest version + // if META-INF/versions exists, no other commandline options like -Djdk.util.jar.version and + // -Djdk.util.jar.enableMultiRelease passed to vm + OutputAnalyzer output = TestCommon.dump(appJar, appClasses); + output.shouldContain("Loading classes to share: done."); + output.shouldHaveExitValue(0); + + output = TestCommon.exec(appJar, verboseMode, mainClass); + checkExecOutput(output, "I am running on version " + MAJOR_VERSION_STRING); + + // 2. Test versions 7 and the current major version. + // -Djdk.util.jar.enableMultiRelease=true (or force), default is true. + // a) -Djdk.util.jar.version=7 does not exist in jar. + // It will fallback to the root version which is also 7 in this test. + // b) -Djdk.util.jar.version=MAJOR_VERSION exists in the jar. + for (int i : new int[] {7, MAJOR_VERSION}) { + jarVersion = "-Djdk.util.jar.version=" + i; + expectedOutput = "I am running on version " + i; + output = TestCommon.dump(appJar, appClasses, enableMultiRelease, jarVersion); + output.shouldContain("Loading classes to share: done."); + output.shouldHaveExitValue(0); + + output = TestCommon.exec(appJar, verboseMode, mainClass); + checkExecOutput(output, expectedOutput); + } + + // 3. For unsupported version, 5 and current major version + 1, the multiversion + // will be turned off, so it will use the default (root) version. + for (int i : new int[] {5, MAJOR_VERSION + 1}) { + jarVersion = "-Djdk.util.jar.version=" + i; + output = TestCommon.dump(appJar, appClasses, enableMultiRelease, jarVersion); + output.shouldHaveExitValue(0); + // With the fix for 8172218, multi-release jar is being handled in + // jdk corelib which doesn't emit the following warning message. + //output.shouldContain("JDK" + i + " is not supported in multiple version jars"); + + output = TestCommon.exec(appJar, verboseMode, mainClass); + if (i == 5) + checkExecOutput(output, "I am running on version 7"); + else + checkExecOutput(output, "I am running on version " + MAJOR_VERSION_STRING); + } + + // 4. If explicitly disabled from command line for multiversion jar, it will use default + // version at root regardless multiversion versions exists. + // -Djdk.util.jar.enableMultiRelease=false (not 'true' or 'force') + for (int i = 6; i < MAJOR_VERSION + 1; i++) { + jarVersion = "-Djdk.util.jar.version=" + i; + output = TestCommon.dump(appJar, appClasses, "-Djdk.util.jar.enableMultiRelease=false", jarVersion); + output.shouldHaveExitValue(0); + + output = TestCommon.exec(appJar, verboseMode, mainClass); + expectedOutput = "I am running on version 7"; + checkExecOutput(output, expectedOutput); + } + + // 5. Sanity test with -Xbootclasspath/a + // AppCDS behaves the same as the non-AppCDS case. A multi-release + // jar file in the -Xbootclasspath/a will be ignored. + output = TestCommon.dump(appJar, appClasses, "-Xbootclasspath/a:" + appJar, enableMultiRelease, jarVersion); + output.shouldContain("Loading classes to share: done."); + output.shouldHaveExitValue(0); + + output = TestCommon.exec(appJar, "-Xbootclasspath/a:" + appJar, verboseMode, mainClass); + checkExecOutput(output, "I am running on version 7"); + + // 6. Sanity test case-insensitive "Multi-Release" attribute name + output = TestCommon.dump(appJar2, appClasses); + output.shouldContain("Loading classes to share: done."); + output.shouldHaveExitValue(0); + + output = TestCommon.exec(appJar2, verboseMode, mainClass); + checkExecOutput(output, "I am running on version " + MAJOR_VERSION_STRING); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/OldClassTest.java b/test/hotspot/jtreg/runtime/appcds/OldClassTest.java new file mode 100644 index 00000000000..d41faf33608 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/OldClassTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, 2017, 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 classes with major version < JDK_1.5 (48) should not be included in CDS + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.org.objectweb.asm + * java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run build TestCommon JarBuilder + * @run main OldClassTest + */ + +import java.io.File; +import java.io.FileOutputStream; +import jdk.test.lib.process.OutputAnalyzer; +import java.nio.file.Files; + +import java.util.*; +import jdk.internal.org.objectweb.asm.*; + +public class OldClassTest implements Opcodes { + + public static void main(String[] args) throws Exception { + File jarSrcFile = new File(JarBuilder.getOrCreateHelloJar()); + + File dir = new File(System.getProperty("test.classes", ".")); + File jarFile = new File(dir, "OldClassTest_old.jar"); + String jar = jarFile.getPath(); + + if (!jarFile.exists() || jarFile.lastModified() < jarSrcFile.lastModified()) { + createTestJarFile(jarSrcFile, jarFile); + } else { + System.out.println("Already up-to-date: " + jarFile); + } + + String appClasses[] = TestCommon.list("Hello"); + + // CASE 1: pre-JDK 1.5 compiled classes should be excluded from the dump + OutputAnalyzer output = TestCommon.dump(jar, appClasses); + TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS"); + + output = TestCommon.execCommon( + "-cp", jar, + "-verbose:class", + "Hello"); + TestCommon.checkExecReturn(output, 0, true, "Hello Unicode world (Old)"); + + // CASE 2: if we exlcude old version of this class, we should not pick up + // the newer version of this class in a subsequent classpath element. + String classpath = jar + File.pathSeparator + jarSrcFile.getPath(); + output = TestCommon.dump(classpath, appClasses); + TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS"); + + output = TestCommon.execCommon( + "-cp", classpath, + "-verbose:class", + "Hello"); + TestCommon.checkExecReturn(output, 0, true, "Hello Unicode world (Old)"); + } + + static void createTestJarFile(File jarSrcFile, File jarFile) throws Exception { + jarFile.delete(); + Files.copy(jarSrcFile.toPath(), jarFile.toPath()); + + File dir = new File(System.getProperty("test.classes", ".")); + File outdir = new File(dir, "old_class_test_classes"); + outdir.delete(); + outdir.mkdir(); + + writeClassFile(new File(outdir, "Hello.class"), makeOldHello()); + + JarBuilder.update(jarFile.getPath(), outdir.getPath()); + } + + static void writeClassFile(File file, byte bytecodes[]) throws Exception { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(bytecodes); + } + } + +/* makeOldHello() was obtained using JDK8. We use a method name > 128 that would + trigger a call to java.lang.Character.isJavaIdentifierStart() during class + file parsing. + +cat > Hello.java <", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitMethodInsn(INVOKESTATIC, "Hello", "\u1234", "()Ljava/lang/String;", false); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "\u1234", "()Ljava/lang/String;", null, null); + mv.visitCode(); + mv.visitLdcInsn("Hello Unicode world (Old)"); + mv.visitInsn(ARETURN); + mv.visitMaxs(1, 0); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/PackageSealing.java b/test/hotspot/jtreg/runtime/appcds/PackageSealing.java new file mode 100644 index 00000000000..00651ee0a3f --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/PackageSealing.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, 2017, 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 AppCDS handling of package. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @compile test-classes/C1.java + * @compile test-classes/C2.java + * @compile test-classes/PackageSealingTest.java + * @run main PackageSealing + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class PackageSealing { + public static void main(String args[]) throws Exception { + String[] classList = {"sealed/pkg/C1", "pkg/C2", "PackageSealingTest"}; + String appJar = ClassFileInstaller.writeJar("pkg_seal.jar", + ClassFileInstaller.Manifest.fromSourceFile("test-classes/package_seal.mf"), + "PackageSealingTest", "sealed/pkg/C1", "pkg/C2"); + + // test shared package from -cp path + TestCommon.testDump(appJar, TestCommon.list(classList)); + OutputAnalyzer output; + output = TestCommon.exec(appJar, "PackageSealingTest"); + TestCommon.checkExec(output, "OK"); + + // test shared package from -Xbootclasspath/a + TestCommon.dump(appJar, TestCommon.list(classList), + "-Xbootclasspath/a:" + appJar); + output = TestCommon.exec(appJar, "-Xbootclasspath/a:" + appJar, "PackageSealingTest"); + TestCommon.checkExec(output, "OK"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/ParallelLoad2.java b/test/hotspot/jtreg/runtime/appcds/ParallelLoad2.java new file mode 100644 index 00000000000..6c07c6bebce --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ParallelLoad2.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, 2017, 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 Load app classes from CDS archive in parallel threads. Similar to ParallelLoad.java, but each class in its own JAR + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/ParallelLoad.java + * @compile test-classes/ParallelClasses.java + * @run main ParallelLoad2 + */ + +import java.io.File; + +public class ParallelLoad2 { + public static int MAX_CLASSES = 40; + public static void main(String[] args) throws Exception { + JarBuilder.build("parallel_load2", "ParallelLoad", "ParallelLoadThread", "ParallelLoadWatchdog"); + for (int i=0; i---------------------------------------------------------------------"); + System.out.println(msg); + System.out.println("<---------------------------------------------------------------------"); + } + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String appJar2 = JarBuilder.build("PrintSharedArchiveAndExit-more", "HelloMore"); + + String cp = appJar + File.pathSeparator + appJar2; + String lastCheckMsg = "checking shared classpath entry: " + appJar2; // the last JAR to check + + TestCommon.testDump(cp, TestCommon.list("Hello")); + + OutputAnalyzer output; + + log("Normal execution -- all the JAR paths should be checked"); + output = TestCommon.execCommon( + "-cp", cp, + "-XX:+PrintSharedArchiveAndExit"); + check(output, 0, true, lastCheckMsg); + + output = TestCommon.execCommon( + "-cp", cp, + "-XX:+PrintSharedArchiveAndExit", + "-XX:+PrintSharedDictionary"); // Test PrintSharedDictionary as well. + check(output, 0, true, lastCheckMsg, "java.lang.Object"); + + log("Normal execution -- Make sure -version, help message and app main()\n" + + "class are not invoked. These are checked inside check()."); + output = TestCommon.execCommon("-cp", cp, "-XX:+PrintSharedArchiveAndExit", "-version"); + check(output, 0, true, lastCheckMsg); + + output = TestCommon.execCommon("-cp", cp, "-XX:+PrintSharedArchiveAndExit", "-help"); + check(output, 0, true, lastCheckMsg); + + output = TestCommon.execCommon("-cp", cp, "-XX:+PrintSharedArchiveAndExit", "Hello"); + check(output, 0, true, lastCheckMsg); + + log("Execution with simple errors -- with 'simple' errors like missing or modified\n" + + "JAR files, the VM should try to continue to print the remaining information.\n" + + "Use an invalid Boot CP -- all the JAR paths should be checked"); + output = TestCommon.execCommon( + "-cp", cp, + "-Xbootclasspath/a:foo.jar", + "-XX:+PrintSharedArchiveAndExit"); + check(output, 1, true, lastCheckMsg, "[BOOT classpath mismatch, "); + + log("Use an App CP shorter than the one at dump time -- all the JAR paths should be checked"); + output = TestCommon.execCommon( + "-cp", ".", + "-XX:+PrintSharedArchiveAndExit"); + check(output, 1, true, lastCheckMsg, "Run time APP classpath is shorter than the one at dump time: ."); + + log("Use an invalid App CP -- all the JAR paths should be checked"); + String invalidCP = "non-existing-dir" + File.pathSeparator + cp; + output = TestCommon.execCommon( + "-cp", invalidCP, + "-XX:+PrintSharedArchiveAndExit"); + check(output, 1, true, lastCheckMsg, "APP classpath mismatch, actual: -Djava.class.path=" + invalidCP); + + log("Changed modification time of hello.jar -- all the JAR paths should be checked"); + (new File(appJar)).setLastModified(System.currentTimeMillis() + 2000); + output = TestCommon.execCommon( + "-cp", cp, + "-XX:+PrintSharedArchiveAndExit"); + check(output, 1, true, lastCheckMsg, "[Timestamp mismatch]"); + + log("Even if hello.jar is out of date, we should still be able to print the dictionary."); + output = TestCommon.execCommon( + "-cp", cp, + "-XX:+PrintSharedArchiveAndExit", + "-XX:+PrintSharedDictionary"); // Test PrintSharedDictionary as well. + check(output, 1, true, lastCheckMsg, "java.lang.Object"); + + + log("Remove hello.jar -- all the JAR paths should be checked"); + (new File(appJar)).delete(); + output = TestCommon.execCommon( + "-cp", cp, + "-XX:+PrintSharedArchiveAndExit"); + check(output, 1, true, lastCheckMsg, "[Required classpath entry does not exist: " + appJar + "]"); + + log("Execution with major errors -- with 'major' errors like the JSA file\n" + + "is missing, we should stop immediately to avoid crashing the JVM."); + output = TestCommon.execCommon( + "-cp", cp, + "-XX:+PrintSharedArchiveAndExit", + "-XX:SharedArchiveFile=./no-such-fileappcds.jsa"); + check(output, 1, false, lastCheckMsg); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java b/test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java new file mode 100644 index 00000000000..92e7227c9c5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, 2017, 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 AppCDS handling of prohibited package. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/ProhibitedHelper.java test-classes/Prohibited.jasm + * @run main ProhibitedPackage + */ + +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +public class ProhibitedPackage { + + public static void main(String[] args) throws Exception { + JarBuilder.build("prohibited_pkg", "java/lang/Prohibited", "ProhibitedHelper"); + + String appJar = TestCommon.getTestJar("prohibited_pkg.jar"); + + // Test support for customer loaders + if (Platform.areCustomLoadersSupportedForCDS()) { + String classlist[] = new String[] { + "java/lang/Object id: 1", + "java/lang/Prohibited id: 2 super: 1 source: " + appJar + }; + + // Make sure a class in a prohibited package for a custom loader + // will be ignored during dumping. + TestCommon.dump(appJar, classlist, "-Xlog:cds") + .shouldContain("Dumping") + .shouldContain("[cds] Prohibited package for non-bootstrap classes: java/lang/Prohibited.class") + .shouldHaveExitValue(0); + } + + + // Make sure a class in a prohibited package for a non-custom loader + // will be ignored during dumping. + TestCommon.dump(appJar, + TestCommon.list("java/lang/Prohibited", "ProhibitedHelper"), + "-Xlog:class+load") + .shouldContain("Dumping") + .shouldNotContain("[info][class,load] java.lang.Prohibited source: ") + .shouldHaveExitValue(0); + + // Try loading the class in a prohibited package with various -Xshare + // modes. The class shouldn't be loaded and appropriate exceptions + // are expected. + + OutputAnalyzer output; + + // -Xshare:on + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper"); + TestCommon.checkExec(output, "Prohibited package name: java.lang"); + + // -Xshare:auto + output = TestCommon.execAuto( + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper"); + TestCommon.checkExec(output, "Prohibited package name: java.lang"); + + // -Xshare:off + output = TestCommon.execOff( + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper"); + output.shouldContain("Prohibited package name: java.lang"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java b/test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java new file mode 100644 index 00000000000..2ff23525a1a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, 2017, 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 AppCDS handling of protection domain. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/ProtDomain.java + * @compile test-classes/ProtDomainB.java + * @compile test-classes/JimageClassProtDomain.java + * @run main ProtectionDomain + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class ProtectionDomain { + public static void main(String[] args) throws Exception { + JarBuilder.build("prot_domain", "ProtDomain", "ProtDomainB", "ProtDomainOther", + "ProtDomainBOther", "JimageClassProtDomain"); + + String appJar = TestCommon.getTestJar("prot_domain.jar"); + TestCommon.testDump(appJar, + TestCommon.list("ProtDomain", + "ProtDomainBOther", + "java/util/Dictionary", + "sun/tools/javac/Main", + "jdk/nio/zipfs/ZipInfo", + "java/net/URL", + "sun/rmi/rmic/Main", + "com/sun/jndi/dns/DnsName")); + + OutputAnalyzer output; + + // First class is loaded from CDS, second class is loaded from JAR + output = TestCommon.exec(appJar, "-verbose:class", "ProtDomain"); + TestCommon.checkExec(output, "Protection Domains match"); + + // First class is loaded from JAR, second class is loaded from CDS + output = TestCommon.exec(appJar, "-verbose:class", "ProtDomainB"); + TestCommon.checkExec(output, "Protection Domains match"); + + // Test ProtectionDomain for application and extension module classes from the + // "modules" jimage + output = TestCommon.exec(appJar, "-verbose:class", "JimageClassProtDomain"); + output.shouldNotContain("Failed: Protection Domains do not match"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/RewriteBytecodesTest.java b/test/hotspot/jtreg/runtime/appcds/RewriteBytecodesTest.java new file mode 100644 index 00000000000..d49587d6bce --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/RewriteBytecodesTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, 2017, 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 Use ClassLoader.defineClass() to load a class with rewritten bytecode. Make sure + * the archived class with the same name is not loaded. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/RewriteBytecodes.java test-classes/Util.java test-classes/Super.java test-classes/Child.java + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main RewriteBytecodesTest + */ + +import java.io.File; +import jdk.test.lib.process.OutputAnalyzer; + +public class RewriteBytecodesTest { + public static void main(String[] args) throws Exception { + String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + String appJar = JarBuilder.build("dynamic_define", "RewriteBytecodes", "Util", "Super", "Child"); + String superClsFile = (new File(System.getProperty("test.classes", "."), "Super.class")).getPath(); + + TestCommon.dump(appJar, TestCommon.list("RewriteBytecodes", "Super", "Child"), + // command-line arguments ... + use_whitebox_jar); + + OutputAnalyzer output = TestCommon.exec(appJar, + // command-line arguments ... + "--add-opens=java.base/java.lang=ALL-UNNAMED", + use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "RewriteBytecodes", superClsFile); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java b/test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java new file mode 100644 index 00000000000..e7b1dac98ed --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2014, 2017, 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 SharedArchiveConsistency + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * jdk.jartool/sun.tools.jar + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @build sun.hotspot.WhiteBox + * @compile test-classes/Hello.java + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SharedArchiveConsistency + */ +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Utils; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import java.nio.file.StandardOpenOption; +import static java.nio.file.StandardOpenOption.READ; +import static java.nio.file.StandardOpenOption.WRITE; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import sun.hotspot.WhiteBox; + +public class SharedArchiveConsistency { + public static WhiteBox wb; + public static int offset_magic; // FileMapHeader::_magic + public static int sp_offset_crc; // FileMapHeader::space_info::_crc + public static int file_header_size = -1;// total size of header, variant, need calculation + public static int space_info_size; // size of space_info + public static int sp_offset; // offset of FileMapHeader::space_info + public static int sp_used_offset; // offset of space_info::_used + public static int size_t_size; // size of size_t + + public static File jsa; // will be updated during test + public static File orgJsaFile; // kept the original file not touched. + public static String[] shared_region_name = {"MiscCode", "ReadWrite", "ReadOnly", "MiscData"}; + public static int num_regions = shared_region_name.length; + public static String[] matchMessages = { + "Unable to use shared archive", + "An error has occurred while processing the shared archive file.", + "Checksum verification failed.", + "The shared archive file has been truncated." + }; + + public static void getFileOffsetInfo() throws Exception { + wb = WhiteBox.getWhiteBox(); + offset_magic = wb.getOffsetForName("FileMapHeader::_magic"); + sp_offset_crc = wb.getOffsetForName("space_info::_crc"); + try { + int nonExistOffset = wb.getOffsetForName("FileMapHeader::_non_exist_offset"); + System.exit(-1); // should fail + } catch (Exception e) { + // success + } + + sp_offset = wb.getOffsetForName("FileMapHeader::_space[0]") - offset_magic; + sp_used_offset = wb.getOffsetForName("space_info::_used") - sp_offset_crc; + size_t_size = wb.getOffsetForName("size_t_size"); + space_info_size = wb.getOffsetForName("space_info_size"); + } + + public static int getFileHeaderSize(FileChannel fc) throws Exception { + if (file_header_size != -1) { + return file_header_size; + } + // this is not real header size, it is struct size + file_header_size = wb.getOffsetForName("file_header_size"); + int offset_path_misc_info = wb.getOffsetForName("FileMapHeader::_paths_misc_info_size") - + offset_magic; + int path_misc_info_size = (int)readInt(fc, offset_path_misc_info, size_t_size); + file_header_size += path_misc_info_size; //readInt(fc, offset_path_misc_info, size_t_size); + System.out.println("offset_path_misc_info = " + offset_path_misc_info); + System.out.println("path_misc_info_size = " + path_misc_info_size); + System.out.println("file_header_size = " + file_header_size); + file_header_size = (int)align_up_page(file_header_size); + System.out.println("file_header_size (aligned to page) = " + file_header_size); + return file_header_size; + } + + public static long align_up_page(long l) throws Exception { + // wb is obtained in getFileOffsetInfo() which is called first in main() else we should call + // WhiteBox.getWhiteBox() here first. + int pageSize = wb.getVMPageSize(); + return (l + pageSize -1) & (~ (pageSize - 1)); + } + + private static long getRandomBetween(long start, long end) throws Exception { + if (start > end) { + throw new IllegalArgumentException("start must be less than end"); + } + Random aRandom = Utils.getRandomInstance(); + int d = aRandom.nextInt((int)(end - start)); + if (d < 1) { + d = 1; + } + return start + d; + } + + public static long readInt(FileChannel fc, long offset, int nbytes) throws Exception { + ByteBuffer bb = ByteBuffer.allocate(nbytes); + bb.order(ByteOrder.nativeOrder()); + fc.position(offset); + fc.read(bb); + return (nbytes > 4 ? bb.getLong(0) : bb.getInt(0)); + } + + public static void writeData(FileChannel fc, long offset, ByteBuffer bb) throws Exception { + fc.position(offset); + fc.write(bb); + fc.force(true); + } + + public static FileChannel getFileChannel() throws Exception { + List arry = new ArrayList(); + arry.add(READ); + arry.add(WRITE); + return FileChannel.open(jsa.toPath(), new HashSet(arry)); + } + + public static void modifyJsaContentRandomly() throws Exception { + FileChannel fc = getFileChannel(); + // corrupt random area in the data areas (MiscCode, ReadWrite, ReadOnly, MiscData) + long[] used = new long[num_regions]; // record used bytes + long start0, start, end, off; + int used_offset, path_info_size; + + int bufSize; + System.out.printf("%-12s%-12s%-12s%-12s%-12s\n", "Space Name", "Offset", "Used bytes", "Reg Start", "Random Offset"); + start0 = getFileHeaderSize(fc); + for (int i = 0; i < num_regions; i++) { + used_offset = sp_offset + space_info_size * i + sp_used_offset; + // read 'used' + used[i] = readInt(fc, used_offset, size_t_size); + start = start0; + for (int j = 0; j < i; j++) { + start += align_up_page(used[j]); + } + end = start + used[i]; + off = getRandomBetween(start, end); + System.out.printf("%-12s%-12d%-12d%-12d%-12d\n", shared_region_name[i], used_offset, used[i], start, off); + if (end - off < 1024) { + bufSize = (int)(end - off + 1); + } else { + bufSize = 1024; + } + ByteBuffer bbuf = ByteBuffer.wrap(new byte[bufSize]); + writeData(fc, off, bbuf); + } + if (fc.isOpen()) { + fc.close(); + } + } + + public static void modifyJsaContent() throws Exception { + FileChannel fc = getFileChannel(); + byte[] buf = new byte[4096]; + ByteBuffer bbuf = ByteBuffer.wrap(buf); + + long total = 0L; + long used_offset = 0L; + long[] used = new long[num_regions]; + System.out.printf("%-12s%-12s\n", "Space name", "Used bytes"); + for (int i = 0; i < num_regions; i++) { + used_offset = sp_offset + space_info_size* i + sp_used_offset; + // read 'used' + used[i] = readInt(fc, used_offset, size_t_size); + System.out.printf("%-12s%-12d\n", shared_region_name[i], used[i]); + total += used[i]; + } + System.out.printf("%-12s%-12d\n", "Total: ", total); + long corrupt_used_offset = getFileHeaderSize(fc); + System.out.println("Corrupt RO section, offset = " + corrupt_used_offset); + while (used_offset < used[0]) { + writeData(fc, corrupt_used_offset, bbuf); + bbuf.clear(); + used_offset += 4096; + } + fc.force(true); + if (fc.isOpen()) { + fc.close(); + } + } + + public static void modifyJsaHeader() throws Exception { + FileChannel fc = getFileChannel(); + // screw up header info + byte[] buf = new byte[getFileHeaderSize(fc)]; + ByteBuffer bbuf = ByteBuffer.wrap(buf); + writeData(fc, 0L, bbuf); + if (fc.isOpen()) { + fc.close(); + } + } + + public static void copyFile(File from, File to) throws Exception { + if (to.exists()) { + if(!to.delete()) { + throw new IOException("Could not delete file " + to); + } + } + to.createNewFile(); + setReadWritePermission(to); + Files.copy(from.toPath(), to.toPath(), REPLACE_EXISTING); + } + + // Copy file with bytes deleted or inserted + // del -- true, deleted, false, inserted + public static void copyFile(File from, File to, boolean del) throws Exception { + FileChannel inputChannel = null; + FileChannel outputChannel = null; + try { + inputChannel = new FileInputStream(from).getChannel(); + outputChannel = new FileOutputStream(to).getChannel(); + long size = inputChannel.size(); + int init_size = getFileHeaderSize(inputChannel); + outputChannel.transferFrom(inputChannel, 0, init_size); + int n = (int)getRandomBetween(0, 1024); + if (del) { + System.out.println("Delete " + n + " bytes at data start section"); + inputChannel.position(init_size + n); + outputChannel.transferFrom(inputChannel, init_size, size - init_size - n); + } else { + System.out.println("Insert " + n + " bytes at data start section"); + outputChannel.position(init_size); + outputChannel.write(ByteBuffer.wrap(new byte[n])); + outputChannel.transferFrom(inputChannel, init_size + n , size - init_size); + } + } finally { + inputChannel.close(); + outputChannel.close(); + } + } + + public static void restoreJsaFile() throws Exception { + Files.copy(orgJsaFile.toPath(), jsa.toPath(), REPLACE_EXISTING); + } + + public static void setReadWritePermission(File file) throws Exception { + if (!file.canRead()) { + if (!file.setReadable(true)) { + throw new IOException("Cannot modify file " + file + " as readable"); + } + } + if (!file.canWrite()) { + if (!file.setWritable(true)) { + throw new IOException("Cannot modify file " + file + " as writable"); + } + } + } + + public static void testAndCheck(String[] execArgs) throws Exception { + OutputAnalyzer output = TestCommon.execCommon(execArgs); + String stdtxt = output.getOutput(); + System.out.println("Note: this test may fail in very rare occasions due to CRC32 checksum collision"); + for (String message : matchMessages) { + if (stdtxt.contains(message)) { + // match any to return + return; + } + } + TestCommon.checkExec(output); + } + + // dump with hello.jsa, then + // read the jsa file + // 1) run normal + // 2) modify header + // 3) keep header correct but modify content + // 4) update both header and content, test + // 5) delete bytes in data begining + // 6) insert bytes in data begining + // 7) randomly corrupt data in four areas: RO, RW. MISC DATA, MISC CODE + public static void main(String... args) throws Exception { + // must call to get offset info first!!! + getFileOffsetInfo(); + Path currentRelativePath = Paths.get(""); + String currentDir = currentRelativePath.toAbsolutePath().toString(); + System.out.println("Current relative path is: " + currentDir); + // get jar file + String jarFile = JarBuilder.getOrCreateHelloJar(); + + // dump (appcds.jsa created) + TestCommon.testDump(jarFile, null); + + // test, should pass + System.out.println("1. Normal, should pass but may fail\n"); + String[] execArgs = {"-cp", jarFile, "Hello"}; + + OutputAnalyzer output = TestCommon.execCommon(execArgs); + + try { + TestCommon.checkExecReturn(output, 0, true, "Hello World"); + } catch (Exception e) { + TestCommon.checkExecReturn(output, 1, true, matchMessages[0]); + } + + // get current archive name + jsa = new File(TestCommon.getCurrentArchiveName()); + if (!jsa.exists()) { + throw new IOException(jsa + " does not exist!"); + } + + setReadWritePermission(jsa); + + // save as original untouched + orgJsaFile = new File(new File(currentDir), "appcds.jsa.bak"); + copyFile(jsa, orgJsaFile); + + + // modify jsa header, test should fail + System.out.println("\n2. Corrupt header, should fail\n"); + modifyJsaHeader(); + output = TestCommon.execCommon(execArgs); + output.shouldContain("The shared archive file has the wrong version"); + output.shouldNotContain("Checksum verification failed"); + + // modify content + System.out.println("\n3. Corrupt Content, should fail\n"); + copyFile(orgJsaFile, jsa); + modifyJsaContent(); + testAndCheck(execArgs); + + // modify both header and content, test should fail + System.out.println("\n4. Corrupt Header and Content, should fail\n"); + copyFile(orgJsaFile, jsa); + modifyJsaHeader(); + modifyJsaContent(); // this will not be reached since failed on header change first + output = TestCommon.execCommon(execArgs); + output.shouldContain("The shared archive file has the wrong version"); + output.shouldNotContain("Checksum verification failed"); + + // delete bytes in data sectoin + System.out.println("\n5. Delete bytes at begining of data section, should fail\n"); + copyFile(orgJsaFile, jsa, true); + testAndCheck(execArgs); + + // insert bytes in data sectoin forward + System.out.println("\n6. Insert bytes at begining of data section, should fail\n"); + copyFile(orgJsaFile, jsa, false); + testAndCheck(execArgs); + + System.out.println("\n7. modify Content in random areas, should fail\n"); + copyFile(orgJsaFile, jsa); + modifyJsaContentRandomly(); + testAndCheck(execArgs); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/SharedArchiveFile.java b/test/hotspot/jtreg/runtime/appcds/SharedArchiveFile.java new file mode 100644 index 00000000000..f18b5f21880 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/SharedArchiveFile.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, 2017, 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 The diagnostic option, -XX:SharedArchiveFile can be unlocked using -XX:+UseAppCDS + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main SharedArchiveFile + */ + +import jdk.test.lib.Platform; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import java.util.Properties; + +public class SharedArchiveFile { + public static void main(String[] args) throws Exception { + boolean isProduct = !Platform.isDebugBuild(); + String appJar = JarBuilder.getOrCreateHelloJar(); + + // 1) Using -XX:SharedArchiveFile without -XX:+UseAppCDS should fail + // on product binary without -XX:+UnlockDiagnosticVMOptions. + if (isProduct) { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-Xshare:dump"); + OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "dump"); + out.shouldContain("Error: VM option 'SharedArchiveFile' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions."); + } + + // 2) Dumping with -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile + // should always succeed. + CDSTestUtils.createArchive("-XX:+UnlockDiagnosticVMOptions") + .shouldContain("Dumping"); + + // 3) Using -XX:SharedArchiveFile with -XX:+UseAppCDS should work + // on product binary by default. + OutputAnalyzer output3 = TestCommon.dump(appJar, TestCommon.list("Hello")); + output3.shouldContain("Dumping"); + output3 = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(output3, "Hello World"); + + // 4) Using -XX:+UseAppCDS should not affect other diagnostic flags, + // such as LogEvents + OutputAnalyzer output4 = TestCommon.exec(appJar, "-XX:+LogEvents", "Hello"); + if (isProduct) { + output4.shouldContain("Error: VM option 'LogEvents' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions."); + } else { + TestCommon.checkExec(output4, "Hello World"); + } + + // 5) 8066921 - Extra -XX:+UseAppCDS + TestCommon.testDump(appJar, TestCommon.list("Hello"), "-XX:+UseAppCDS"); + OutputAnalyzer output5 = TestCommon.exec(appJar, "-XX:+UseAppCDS", "Hello"); + TestCommon.checkExec(output5); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/SharedBaseAddress.java b/test/hotspot/jtreg/runtime/appcds/SharedBaseAddress.java new file mode 100644 index 00000000000..b317aac0d8f --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/SharedBaseAddress.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, 2017, 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 SharedBaseAddress + * @summary Test variety of values for SharedBaseAddress, in AppCDS mode, + * making sure VM handles normal values as well as edge values + * w/o a crash. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main/timeout=240 SharedBaseAddress + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class SharedBaseAddress { + + // shared base address test table + private static final String[] testTable = { + "1g", "8g", "64g","512g", "4t", + "32t", "128t", "0", + "1", "64k", "64M" + }; + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + + for (String testEntry : testTable) { + System.out.println("sharedBaseAddress = " + testEntry); + + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, new String[] {"Hello"}, "-XX:SharedBaseAddress=" + testEntry); + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(execOutput, "Hello World"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/SharedPackages.java b/test/hotspot/jtreg/runtime/appcds/SharedPackages.java new file mode 100644 index 00000000000..c748d53c39c --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/SharedPackages.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014, 2017, 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 AppCDS handling of package. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/PackageTest.java + * @compile test-classes/JimageClassPackage.java + * @run main SharedPackages + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class SharedPackages { + public static void main(String[] args) throws Exception { + JarBuilder.build("pkg", "p/PackageTest", "JimageClassPackage"); + + String appJar = TestCommon.getTestJar("pkg.jar"); + TestCommon.testDump(appJar, TestCommon.list("p/PackageTest", + "java/util/Dictionary", + "sun/tools/javac/Main", + "jdk/nio/zipfs/ZipInfo", + "java/net/URL", + "sun/rmi/rmic/Main", + "com/sun/jndi/dns/DnsName")); + + OutputAnalyzer output; + + // Test 1: shared class from Jar on the -cp + output = TestCommon.exec(appJar, "-verbose:class", "p.PackageTest"); + TestCommon.checkExec(output, "Expected package"); + if (!TestCommon.isUnableToMap(output)) + output.shouldContain("Package is not sealed"); + + // Test 2: shared classes from "modules" jimage + output = TestCommon.exec(appJar, "-verbose:class", + "JimageClassPackage"); + if (!TestCommon.isUnableToMap(output)) { + output.shouldNotContain("Unexpected package"); + output.shouldNotContain("Package is not sealed"); + } + + // Test 3: shared class from Jar on the -Xbootclasspath/a + TestCommon.dump( + appJar, TestCommon.list("p/PackageTest"), "-Xbootclasspath/a:" + appJar); + output = TestCommon.exec(appJar, "-Xbootclasspath/a:" + appJar, "p.PackageTest"); + if (!TestCommon.isUnableToMap(output)) { + output.shouldNotContain("Unexpected package"); + output.shouldContain("Package is not sealed"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/SignedJar.java b/test/hotspot/jtreg/runtime/appcds/SignedJar.java new file mode 100644 index 00000000000..7c3391ea034 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/SignedJar.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 2017, 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 AppCDS handling of signed JAR. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main SignedJar + */ + +import jdk.test.lib.process.OutputAnalyzer; +import java.io.File; + +public class SignedJar { + public static void main(String[] args) throws Exception { + String unsignedJar = JarBuilder.getOrCreateHelloJar(); + JarBuilder.signJar(); + + // Test class exists in signed JAR + String signedJar = TestCommon.getTestJar("signed_hello.jar"); + OutputAnalyzer output; + output = TestCommon.dump(signedJar, TestCommon.list("Hello")); + TestCommon.checkDump(output, "Preload Warning: Skipping Hello from signed JAR"); + + // At runtime, the Hello class should be loaded from the jar file + // instead of from the shared archive since a class from a signed + // jar shouldn't be dumped into the archive. + output = TestCommon.exec(signedJar, "-verbose:class", "Hello"); + String expectedOutput = ".class,load. Hello source: file:.*signed_hello.jar"; + + try { + output.shouldMatch(expectedOutput); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + + // Test class exists in both signed JAR and unsigned JAR + String jars = signedJar + System.getProperty("path.separator") + unsignedJar; + output = TestCommon.dump(jars, TestCommon.list("Hello")); + TestCommon.checkDump(output, "Preload Warning: Skipping Hello from signed JAR"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/SpecifySysLoaderProp.java b/test/hotspot/jtreg/runtime/appcds/SpecifySysLoaderProp.java new file mode 100644 index 00000000000..bea6a0ac3f0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/SpecifySysLoaderProp.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014, 2017, 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 If -Djava.system.class.loader=xxx is specified in command-line, disable UseAppCDS + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @compile test-classes/TestClassLoader.java + * @compile test-classes/ReportMyLoader.java + * @compile test-classes/TrySwitchMyLoader.java + * @run main SpecifySysLoaderProp + */ + +import java.io.*; +import jdk.test.lib.process.OutputAnalyzer; + +public class SpecifySysLoaderProp { + + public static void main(String[] args) throws Exception { + JarBuilder.build("sysloader", "TestClassLoader", "ReportMyLoader", "TrySwitchMyLoader"); + + String jarFileName = "sysloader.jar"; + String appJar = TestCommon.getTestJar(jarFileName); + TestCommon.testDump(appJar, TestCommon.list("ReportMyLoader")); + String warning = "VM warning: UseAppCDS is disabled because the java.system.class.loader property is specified"; + + + // (0) Baseline. Do not specify -Djava.system.class.loader + // The test class should be loaded from archive + OutputAnalyzer output = TestCommon.execCommon( + "-verbose:class", + "-cp", appJar, + "ReportMyLoader"); + TestCommon.checkExec(output, + "[class,load] ReportMyLoader source: shared objects file", + "ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@"); + + // (1) Try to execute the archive with -Djava.system.class.loader=no.such.Klass, + // it should fail + output = TestCommon.execCommon( + "-cp", appJar, + "-Djava.system.class.loader=no.such.Klass", + "ReportMyLoader"); + try { + output.shouldContain(warning); + output.shouldContain("ClassNotFoundException: no.such.Klass"); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + + // (2) Try to execute the archive with -Djava.system.class.loader=TestClassLoader, + // it should run, but AppCDS should be disabled + output = TestCommon.execCommon( + "-verbose:class", + "-cp", appJar, + "-Djava.system.class.loader=TestClassLoader", + "ReportMyLoader"); + TestCommon.checkExec(output, + "ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@", //<-this is still printed because TestClassLoader simply delegates to Launcher$AppLoader, but ... + "TestClassLoader.called = true", //<-but this proves that TestClassLoader was indeed called. + "TestClassLoader: loadClass(\"ReportMyLoader\","); //<- this also proves that TestClassLoader was indeed called. + try { + output.shouldMatch(".class,load. TestClassLoader source: file:"); + output.shouldMatch(".class,load. ReportMyLoader source: file:.*" + jarFileName); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + + // (3) Try to change the java.system.class.loader programmatically after + // the app's main method is executed. This should have no effect in terms of + // changing or switching the actual system class loader that's already in use. + output = TestCommon.execCommon( + "-verbose:class", + "-cp", appJar, + "TrySwitchMyLoader"); + TestCommon.checkExec(output, + "[class,load] ReportMyLoader source: shared objects file", + "TrySwitchMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@", + "ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@", + "TestClassLoader.called = false"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/appcds/TestCommon.java new file mode 100644 index 00000000000..ad6f8e272cb --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import jdk.test.lib.Utils; +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.Platform; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +/** + * This is a test utility class for common AppCDS test functionality. + * + * Various methods use (String ...) for passing VM options. Note that the order + * of the VM options are important in certain cases. Many methods take arguments like + * + * (String prefix[], String suffix[], String... opts) + * + * Note that the order of the VM options is: + * + * prefix + opts + suffix + */ +public class TestCommon extends CDSTestUtils { + private static final String JSA_FILE_PREFIX = System.getProperty("user.dir") + + File.separator + "appcds-"; + + private static final SimpleDateFormat timeStampFormat = + new SimpleDateFormat("HH'h'mm'm'ss's'SSS"); + + private static final String timeoutFactor = + System.getProperty("test.timeout.factor", "1.0"); + + private static String currentArchiveName; + + // Call this method to start new archive with new unique name + public static void startNewArchiveName() { + deletePriorArchives(); + currentArchiveName = JSA_FILE_PREFIX + + timeStampFormat.format(new Date()) + ".jsa"; + } + + // Call this method to get current archive name + public static String getCurrentArchiveName() { + return currentArchiveName; + } + + // Attempt to clean old archives to preserve space + // Archives are large artifacts (20Mb or more), and much larger than + // most other artifacts created in jtreg testing. + // Therefore it is a good idea to clean the old archives when they are not needed. + // In most cases the deletion attempt will succeed; on rare occasion the + // delete operation will fail since the system or VM process still holds a handle + // to the file; in such cases the File.delete() operation will silently fail, w/o + // throwing an exception, thus allowing testing to continue. + public static void deletePriorArchives() { + File dir = new File(System.getProperty("user.dir")); + String files[] = dir.list(); + for (String name : files) { + if (name.startsWith("appcds-") && name.endsWith(".jsa")) { + if (!(new File(dir, name)).delete()) + System.out.println("deletePriorArchives(): delete failed for file " + name); + } + } + } + + + // Create AppCDS archive using most common args - convenience method + // Legacy name preserved for compatibility + public static OutputAnalyzer dump(String appJar, String appClasses[], + String... suffix) throws Exception { + return createArchive(appJar, appClasses, suffix); + } + + + // Create AppCDS archive using most common args - convenience method + public static OutputAnalyzer createArchive(String appJar, String appClasses[], + String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar) + .setAppClasses(appClasses); + opts.addSuffix(suffix); + return createArchive(opts); + } + + + // Create AppCDS archive using appcds options + public static OutputAnalyzer createArchive(AppCDSOptions opts) + throws Exception { + + ArrayList cmd = new ArrayList(); + File classList = makeClassList(opts.appClasses); + startNewArchiveName(); + + for (String p : opts.prefix) cmd.add(p); + + if (opts.appJar != null) { + cmd.add("-cp"); + cmd.add(opts.appJar); + } else { + cmd.add("-cp"); + cmd.add("\"\""); + } + + cmd.add("-Xshare:dump"); + cmd.add("-Xlog:cds,cds+hashtables"); + cmd.add("-XX:+UseAppCDS"); + cmd.add("-XX:ExtraSharedClassListFile=" + classList.getPath()); + + if (opts.archiveName == null) + opts.archiveName = getCurrentArchiveName(); + + cmd.add("-XX:SharedArchiveFile=" + opts.archiveName); + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + return executeAndLog(pb, "dump"); + } + + + // Execute JVM using AppCDS archive with specified AppCDSOptions + public static OutputAnalyzer runWithArchive(AppCDSOptions opts) + throws Exception { + + ArrayList cmd = new ArrayList(); + + for (String p : opts.prefix) cmd.add(p); + + cmd.add("-Xshare:" + opts.xShareMode); + cmd.add("-XX:+UseAppCDS"); + cmd.add("-showversion"); + cmd.add("-XX:SharedArchiveFile=" + getCurrentArchiveName()); + cmd.add("-Dtest.timeout.factor=" + timeoutFactor); + + if (opts.appJar != null) { + cmd.add("-cp"); + cmd.add(opts.appJar); + } + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + return executeAndLog(pb, "exec"); + } + + + public static OutputAnalyzer execCommon(String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()); + opts.addSuffix(suffix); + return runWithArchive(opts); + } + + + public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar); + opts.addSuffix(suffix); + return runWithArchive(opts); + } + + + public static OutputAnalyzer execAuto(String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()); + opts.addSuffix(suffix).setXShareMode("auto"); + return runWithArchive(opts); + } + + public static OutputAnalyzer execOff(String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()); + opts.addSuffix(suffix).setXShareMode("off"); + return runWithArchive(opts); + } + + public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath, + String mid, String... testClassArgs) + throws Exception { + + AppCDSOptions opts = (new AppCDSOptions()); + + opts.addPrefix(prefix); + if (upgrademodulepath == null) { + opts.addSuffix("-p", modulepath, "-m", mid); + } else { + opts.addSuffix("--upgrade-module-path", upgrademodulepath, + "-p", modulepath, "-m", mid); + } + opts.addSuffix(testClassArgs); + + return runWithArchive(opts); + } + + + // A common operation: dump, then check results + public static OutputAnalyzer testDump(String appJar, String appClasses[], + String... suffix) throws Exception { + OutputAnalyzer output = dump(appJar, appClasses, suffix); + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + return output; + } + + + /** + * Simple test -- dump and execute appJar with the given appClasses in classlist. + */ + public static OutputAnalyzer test(String appJar, String appClasses[], String... args) + throws Exception { + testDump(appJar, appClasses); + + OutputAnalyzer output = exec(appJar, args); + return checkExec(output); + } + + + public static OutputAnalyzer checkExecReturn(OutputAnalyzer output, int ret, + boolean checkContain, String... matches) throws Exception { + try { + for (String s : matches) { + if (checkContain) { + output.shouldContain(s); + } else { + output.shouldNotContain(s); + } + } + output.shouldHaveExitValue(ret); + } catch (Exception e) { + checkCommonExecExceptions(output, e); + } + + return output; + } + + + // Convenience concatenation utils + public static String[] list(String ...args) { + return args; + } + + + public static String[] list(String arg, int count) { + ArrayList stringList = new ArrayList(); + for (int i = 0; i < count; i++) { + stringList.add(arg); + } + + String outputArray[] = stringList.toArray(new String[stringList.size()]); + return outputArray; + } + + + public static String[] concat(String... args) { + return list(args); + } + + + public static String[] concat(String prefix[], String... extra) { + ArrayList list = new ArrayList(); + for (String s : prefix) { + list.add(s); + } + for (String s : extra) { + list.add(s); + } + + return list.toArray(new String[list.size()]); + } + + + // ===================== Concatenate paths + public static String concatPaths(String... paths) { + String prefix = ""; + String s = ""; + for (String p : paths) { + s += prefix; + s += p; + prefix = File.pathSeparator; + } + return s; + } + + + public static String getTestJar(String jar) { + File jarFile = CDSTestUtils.getTestArtifact(jar, true); + if (!jarFile.isFile()) { + throw new RuntimeException("Not a regular file: " + jarFile.getPath()); + } + return jarFile.getPath(); + } + + + public static String getTestDir(String d) { + File dirFile = CDSTestUtils.getTestArtifact(d, true); + if (!dirFile.isDirectory()) { + throw new RuntimeException("Not a directory: " + dirFile.getPath()); + } + return dirFile.getPath(); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/TraceLongClasspath.java b/test/hotspot/jtreg/runtime/appcds/TraceLongClasspath.java new file mode 100644 index 00000000000..b3f73278dba --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/TraceLongClasspath.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, 2017, 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 ensure -XX:+TraceClassPaths showing entire expecting app classpath + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main TraceLongClasspath + */ + +import java.io.File; +import jdk.test.lib.process.OutputAnalyzer; + +public class TraceLongClasspath { + + final static String ps = File.pathSeparator; + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + + String longClassPath = + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/user-patch.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/abc-startup.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/features/com.foobar.db.jdbc7-dms.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/server/lib/someapps.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/../foobar_common/modules/net.xy.batcontrib_1.1.0.0_1-0b3/lib/bat-contrib.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/modules/features/foobar.aas.common.kkkkkkkkkkk.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.common.adapters_11.1.1/foobar.abc.common.adapters.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.plane.adapter_12.1.3/foobar.plane.adapter.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/lib/ccccccccar-common.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/communications/modules/config.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/communications/modules/userprefs-config.jar" + ps + + "/scratch/xxxx/yyyy/XXXXXX/aaaaaaaa/xxxxxxx/xxxxxxxx.us.foobar.com/CommonDomain/config/abc-infra" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/qqqqqq-all-1.6.5.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/foobar.abc.thread.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/thread-rrrrrrr-ext-aas.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.adapter_11.1.1/foobar.abc.adapter.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.ccc_11.1.1/foobar.abc.ccc.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-configuration.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-lang.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-logging.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.wccore/foobar-ppppppp-api.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/internal/features/rrr_aaxyxx_foobar.rrr.aas.classpath.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/rrrrrrrr-api.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/commons-xxx-1.1.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.mgmt_11.1.1/abc-infra-mgmt.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/eee/archives/eee-eee.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/marchnet.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/marchclient.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/march.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/jlib/iiiloader.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/xxxxxxyyzzzzz/classes-xxxxxxyyzzzzz.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_core.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_codec.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_imageio.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar"; + + longClassPath += ps + appJar; + // Dump an archive with a specified JAR file in -classpath + TestCommon.testDump(longClassPath, TestCommon.list("Hello")); + + // Then try to execute the archive with a different classpath and with -XX:+TraceClassPaths. + // The diagnosis "expecting" app classpath trace should show the entire classpath. + OutputAnalyzer output = TestCommon.execCommon( + "-XX:+TraceClassPaths", + "-cp", appJar, + "Hello"); + output.shouldContain("Unable to use shared archive"); + output.shouldContain("shared class paths mismatch"); + // the "expecting" app classpath from -XX:+TraceClassPaths should not + // be truncated + output.shouldContain(longClassPath); + output.shouldHaveExitValue(1); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/UseAppCDS.java b/test/hotspot/jtreg/runtime/appcds/UseAppCDS.java new file mode 100644 index 00000000000..639c06de59c --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/UseAppCDS.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2014, 2017, 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 Testing use of UseAppCDS flag + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @build UseAppCDS_Test + * @run main UseAppCDS + */ + +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.util.ArrayList; +import java.util.List; +import java.io.*; + +public class UseAppCDS { + + // Class UseAppCDS_Test is loaded by the App loader + + static final String TEST_OUT = "UseAppCDS_Test.main--executed"; + + private static final String TESTJAR = "./test.jar"; + private static final String TESTNAME = "UseAppCDS_Test"; + private static final String TESTCLASS = TESTNAME + ".class"; + + private static final String CLASSES_DIR = System.getProperty("test.classes", "."); + private static final String CLASSLIST_FILE = "./UseAppCDS.classlist"; + private static final String ARCHIVE_FILE = "./shared.jsa"; + private static final String BOOTCLASS = "java.lang.Class"; + + public static void main(String[] args) throws Exception { + + // First create a jar file for the application "test" class + JDKToolLauncher jar = JDKToolLauncher.create("jar") + .addToolArg("-cf") + .addToolArg(TESTJAR) + .addToolArg("-C") + .addToolArg(CLASSES_DIR) + .addToolArg(TESTCLASS); + + ProcessBuilder pb = new ProcessBuilder(jar.getCommand()); + TestCommon.executeAndLog(pb, "jar01").shouldHaveExitValue(0); + + pb = new ProcessBuilder(jar.getCommand()); + TestCommon.executeAndLog(pb, "jar02").shouldHaveExitValue(0); + + // In all tests the BOOTCLASS should be loaded/dumped/used + + // Test 1: No AppCDS - dumping loaded classes excludes the "test" classes + dumpLoadedClasses(false, new String[] { BOOTCLASS }, + new String[] { TESTNAME }); + + // Test 2: AppCDS - dumping loaded classes includes "test" classes + dumpLoadedClasses(true, new String[] { BOOTCLASS, TESTNAME }, + new String[0]); + + // Next tests rely on the classlist we just dumped + + // Test 3: No AppCDS - "test" classes in classlist ignored when dumping + dumpArchive(false, new String[] { BOOTCLASS }, + new String[] { TESTNAME}); + + // Test 4: AppCDS - "test" classes in classlist are dumped + dumpArchive(true, new String[] { BOOTCLASS, TESTNAME }, + new String[0]); + + // Next tests rely on the archive we just dumped + + // Test 5: No AppCDS - Using archive containing "test" classes ignores them + useArchive(false, new String[] { BOOTCLASS }, + new String[] { TESTNAME }); + + // Test 6: AppCDS - Using archive containing "test" classes loads them + useArchive(true, new String[] { BOOTCLASS, TESTNAME }, + new String[0]); + } + + public static List toClassNames(String filename) throws IOException { + ArrayList classes = new ArrayList<>(); + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename))); + for (; ; ) { + String line = br.readLine(); + if (line == null) + break; + classes.add(line.replaceAll("/", ".")); + } + return classes; + } + + static void dumpLoadedClasses(boolean useAppCDS, String[] expectedClasses, + String[] unexpectedClasses) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + true, + "-XX:DumpLoadedClassList=" + CLASSLIST_FILE, + "-cp", + TESTJAR, + useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", + TESTNAME, + TEST_OUT); + + OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-loaded-classes") + .shouldHaveExitValue(0).shouldContain(TEST_OUT); + + List dumpedClasses = toClassNames(CLASSLIST_FILE); + + for (String clazz : expectedClasses) { + if (!dumpedClasses.contains(clazz)) { + throw new RuntimeException(clazz + " missing in " + + CLASSLIST_FILE); + } + } + for (String clazz : unexpectedClasses) { + if (dumpedClasses.contains(clazz)) { + throw new RuntimeException("Unexpectedly found " + clazz + + " in " + CLASSLIST_FILE); + } + } + } + + static void dumpArchive(boolean useAppCDS, String[] expectedClasses, + String[] unexpectedClasses) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + true, + useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" : + "-XX:+UnlockDiagnosticVMOptions", + "-cp", + TESTJAR, + useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", + "-XX:SharedClassListFile=" + CLASSLIST_FILE, + "-XX:SharedArchiveFile=" + ARCHIVE_FILE, + "-Xlog:cds", + "-Xshare:dump"); + + OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-archive") + .shouldHaveExitValue(0); + + for (String clazz : expectedClasses) { + String failed = "Preload Warning: Cannot find " + clazz; + output.shouldNotContain(failed); + } + for (String clazz : unexpectedClasses) { + String failed = "Preload Warning: Cannot find " + clazz; + output.shouldContain(failed); + } + } + + static void useArchive(boolean useAppCDS, String[] expectedClasses, + String[] unexpectedClasses) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + true, + useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" : + "-XX:+UnlockDiagnosticVMOptions", + "-cp", + TESTJAR, + useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", + "-XX:SharedArchiveFile=" + ARCHIVE_FILE, + "-verbose:class", + "-Xshare:on", + TESTNAME, + TEST_OUT ); + + OutputAnalyzer output = TestCommon.executeAndLog(pb, "use-archive"); + if (CDSTestUtils.isUnableToMap(output)) + System.out.println("Unable to map: test case skipped"); + else + output.shouldHaveExitValue(0).shouldContain(TEST_OUT); + + // Quote the class name in the regex as it may contain $ + String prefix = ".class,load. "; + String archive_suffix = ".*source: shared objects file.*"; + String jar_suffix = ".*source: .*\\.jar"; + + for (String clazz : expectedClasses) { + String pattern = prefix + clazz + archive_suffix; + try { + output.shouldMatch(pattern); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + } + + for (String clazz : unexpectedClasses) { + String pattern = prefix + clazz + archive_suffix; + try { + output.shouldNotMatch(pattern); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + pattern = prefix + clazz + jar_suffix; + try { + output.shouldMatch(pattern); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/UseAppCDS_Test.java b/test/hotspot/jtreg/runtime/appcds/UseAppCDS_Test.java new file mode 100644 index 00000000000..438c614445b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/UseAppCDS_Test.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ +public class UseAppCDS_Test { + // args are from UseAppCDS: + // args[0] = TEST_OUT + public static void main(String[] args) { + System.out.println(args[0]); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/VerifierTest.java b/test/hotspot/jtreg/runtime/appcds/VerifierTest.java new file mode 100644 index 00000000000..ba7f5d1b831 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/VerifierTest.java @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.File; +import java.io.FileOutputStream; +import jdk.test.lib.process.OutputAnalyzer; +import java.nio.file.Files; + +import java.util.*; +import jdk.internal.org.objectweb.asm.*; + +/** + * The testsets contained in this class are executed by ./VerifierTest_*.java, so that + * individual testsets can be executed in parallel to shorten the total time required. + */ +public class VerifierTest implements Opcodes { + // Test verification settings for dumping & runtime + static final String VFY_ALL = "-Xverify:all"; + static final String VFY_REMOTE = "-Xverify:remote"; // default + static final String VFY_NONE = "-Xverify:none"; + + static final String ERR = + "ERROR: class VerifierTestC was loaded unexpectedly"; + static final String MAP_FAIL = + "shared archive file was created with less restrictive verification setting"; + static final String VFY_ERR = "java.lang.VerifyError"; + + enum Testset1Part { + A, B + } + + public static void main(String[] args) throws Exception { + String subCaseId = args[0]; + String jarName_verifier_test_tmp = "verifier_test_tmp" + "_" + subCaseId; + String jarName_verifier_test = "verifier_test" + "_" + subCaseId; + String jarName_greet = "greet" + "_" + subCaseId; + String jarName_hi = "hi" + "_" + subCaseId; + + + JarBuilder.build(jarName_verifier_test_tmp, "VerifierTest0", "VerifierTestA", + "VerifierTestB", "VerifierTestC", "VerifierTestD", "VerifierTestE", + "UnverifiableBase", "UnverifiableIntf", "UnverifiableIntfSub"); + JarBuilder.build(jarName_greet, "Greet"); + JarBuilder.build(jarName_hi, "Hi", "Hi$MyClass"); + + File dir = new File(System.getProperty("test.classes", ".")); + File jarSrcFile = new File(dir, jarName_verifier_test_tmp + ".jar"); + File jarFile = new File(dir, jarName_verifier_test + ".jar"); + String jar = jarFile.getPath(); + + if (!jarFile.exists() || jarFile.lastModified() < jarSrcFile.lastModified()) { + createTestJarFile(jarSrcFile, jarFile); + } else { + System.out.println("Already up-to-date: " + jarFile); + } + + String noAppClasses[] = TestCommon.list(""); + String appClasses[] = TestCommon.list("UnverifiableBase", + "UnverifiableIntf", + "UnverifiableIntfSub", + "VerifierTestA", + "VerifierTestB", + "VerifierTestC", + "VerifierTestD", + "VerifierTestE", + "VerifierTest0"); + + + switch (subCaseId) { + case "0": testset_0(jar, noAppClasses, appClasses); return; + case "1A": testset_1(jar, noAppClasses, appClasses, Testset1Part.A); return; + case "1B": testset_1(jar, noAppClasses, appClasses, Testset1Part.B); return; + case "2": testset_2(jarName_greet, jarName_hi); return; + default: + throw new RuntimeException("Unknown option: " + subCaseId); + } + } + + static void testset_0(String jar, String[] noAppClasses, String[] appClasses) throws Exception { + // Dumping should fail if the IgnoreUnverifiableClassesDuringDump + // option is not enabled. + OutputAnalyzer output = TestCommon.dump(jar, appClasses, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:-IgnoreUnverifiableClassesDuringDump"); + output.shouldContain("Please remove the unverifiable classes"); + output.shouldHaveExitValue(1); + + // By default, bad classes should be ignored during dumping. + TestCommon.testDump(jar, appClasses); + } + + static void testset_1(String jar, String[] noAppClasses, String[] appClasses, Testset1Part part) + throws Exception + { + String config[][] = { + // {dump_list, dumptime_verification_setting, + // runtime_verification_setting, runtime_output}, + + // Dump app/ext with -Xverify:remote + {"app", VFY_REMOTE, VFY_REMOTE, VFY_ERR}, + {"app", VFY_REMOTE, VFY_ALL, MAP_FAIL}, + {"app", VFY_REMOTE, VFY_NONE, ERR }, + // Dump app/ext with -Xverify:all + {"app", VFY_ALL, VFY_REMOTE, VFY_ERR }, + {"app", VFY_ALL, VFY_ALL, VFY_ERR }, + {"app", VFY_ALL, VFY_NONE, ERR }, + // Dump app/ext with -Xverify:none + {"app", VFY_NONE, VFY_REMOTE, MAP_FAIL}, + {"app", VFY_NONE, VFY_ALL, MAP_FAIL}, + {"app", VFY_NONE, VFY_NONE, ERR }, + // Dump sys only with -Xverify:remote + {"noApp", VFY_REMOTE, VFY_REMOTE, VFY_ERR}, + {"noApp", VFY_REMOTE, VFY_ALL, VFY_ERR}, + {"noApp", VFY_REMOTE, VFY_NONE, ERR}, + // Dump sys only with -Xverify:all + {"noApp", VFY_ALL, VFY_REMOTE, VFY_ERR}, + {"noApp", VFY_ALL, VFY_ALL, VFY_ERR}, + {"noApp", VFY_ALL, VFY_NONE, ERR}, + // Dump sys only with -Xverify:none + {"noApp", VFY_NONE, VFY_REMOTE, VFY_ERR}, + {"noApp", VFY_NONE, VFY_ALL, VFY_ERR}, + {"noApp", VFY_NONE, VFY_NONE, ERR}, + }; + + int loop_start, loop_stop; + + // Further break down testset_1 into two parts (to be invoked from VerifierTest_1A.java + // and VerifierTest_1B.java) to improve parallel test execution time. + switch (part) { + case A: + loop_start = 0; + loop_stop = 9; + break; + case B: + default: + assert part == Testset1Part.B; + loop_start = 9; + loop_stop = config.length; + break; + } + + String prev_dump_setting = ""; + for (int i = loop_start; i < loop_stop; i ++) { + String dump_list[] = config[i][0].equals("app") ? appClasses : + noAppClasses; + String dump_setting = config[i][1]; + String runtime_setting = config[i][2]; + String runtime_output = config[i][3]; + System.out.println("Test case [" + i + "]: dumping " + config[i][0] + + " with " + dump_setting + + ", run with " + runtime_setting); + if (!dump_setting.equals(prev_dump_setting)) { + OutputAnalyzer dumpOutput = TestCommon.dump( + jar, dump_list, dump_setting, + // FIXME: the following options are for working around a GC + // issue - assert failure when dumping archive with the -Xverify:all + "-Xms256m", + "-Xmx256m"); + } + OutputAnalyzer runtimeOutput = TestCommon.execCommon( + "-cp", jar, + runtime_setting, + "VerifierTest0"); + try { + runtimeOutput.shouldContain(runtime_output); + } catch (RuntimeException re) { + // Check if the failure is due to archive mapping failure. + // If not, a RuntimeException will be thrown. + runtimeOutput.shouldContain("Unable to use shared archive"); + } + prev_dump_setting = dump_setting; + } + } + + static void testset_2(String jarName_greet, String jarName_hi) throws Exception { + String appClasses[]; + String jar; + + // The following section is for testing the scenarios where + // the classes are verifiable during dump time. + appClasses = TestCommon.list("Hi", + "Greet", + "Hi$MyClass"); + jar = TestCommon.getTestJar(jarName_hi + ".jar") + File.pathSeparator + + TestCommon.getTestJar(jarName_greet + ".jar"); + final String PASS_RESULT = "Hi, how are you?"; + String config2[][] = { + // {dump_list, dumptime_verification_setting, + // runtime_verification_setting, runtime_output}, + + // Dump app/ext with -Xverify:remote + {"app", VFY_REMOTE, VFY_REMOTE, PASS_RESULT}, + {"app", VFY_REMOTE, VFY_ALL, MAP_FAIL}, + {"app", VFY_REMOTE, VFY_NONE, PASS_RESULT }, + // Dump app/ext with -Xverify:all + {"app", VFY_ALL, VFY_REMOTE, PASS_RESULT }, + {"app", VFY_ALL, VFY_ALL, PASS_RESULT }, + {"app", VFY_ALL, VFY_NONE, PASS_RESULT }, + // Dump app/ext with -Xverify:none + {"app", VFY_NONE, VFY_REMOTE, MAP_FAIL}, + {"app", VFY_NONE, VFY_ALL, MAP_FAIL}, + {"app", VFY_NONE, VFY_NONE, PASS_RESULT }, + }; + for (int i = 0; i < config2.length; i ++) { + // config2[i][0] is always set to "app" in this test + String dump_setting = config2[i][1]; + String runtime_setting = config2[i][2]; + String runtime_output = config2[i][3]; + System.out.println("Test case [" + i + "]: dumping " + config2[i][0] + + " with " + dump_setting + + ", run with " + runtime_setting); + OutputAnalyzer dumpOutput = TestCommon.dump( + jar, appClasses, dump_setting, + "-XX:+UnlockDiagnosticVMOptions", + // FIXME: the following options are for working around a GC + // issue - assert failure when dumping archive with the -Xverify:all + "-Xms256m", + "-Xmx256m"); + OutputAnalyzer runtimeOutput = TestCommon.execCommon( + "-cp", jar, + runtime_setting, + "Hi"); + try { + runtimeOutput.shouldContain(runtime_output); + } catch (RuntimeException re) { + // Check if the failure is due to archive mapping failure. + // If not, a RuntimeException will be thrown. + runtimeOutput.shouldContain("Unable to use shared archive"); + } + } + + } + + static void createTestJarFile(File jarSrcFile, File jarFile) throws Exception { + jarFile.delete(); + Files.copy(jarSrcFile.toPath(), jarFile.toPath()); + + File dir = new File(System.getProperty("test.classes", ".")); + File outdir = new File(dir, "verifier_test_classes"); + outdir.mkdir(); + + writeClassFile(new File(outdir, "UnverifiableBase.class"), makeUnverifiableBase()); + writeClassFile(new File(outdir, "UnverifiableIntf.class"), makeUnverifiableIntf()); + + JarBuilder.update(jarFile.getPath(), outdir.getPath()); + } + + static void writeClassFile(File file, byte bytecodes[]) throws Exception { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(bytecodes); + } + } + + // This was obtained using JDK8: java jdk.internal.org.objectweb.asm.util.ASMifier tmpclasses/UnverifiableBase.class + static byte[] makeUnverifiableBase() throws Exception { + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V1_6, ACC_SUPER, "UnverifiableBase", null, "java/lang/Object", null); + { + fv = cw.visitField(ACC_FINAL + ACC_STATIC, "x", "LVerifierTest;", null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(0, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "", "()V", null, null); + mv.visitCode(); + //WAS mv.visitTypeInsn(NEW, "VerifierTest"); + mv.visitTypeInsn(NEW, "java/lang/Object"); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, "VerifierTest0", "", "()V", false); + mv.visitFieldInsn(PUTSTATIC, "UnverifiableBase", "x", "LVerifierTest;"); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 0); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } + + // This was obtained using JDK8: java jdk.internal.org.objectweb.asm.util.ASMifier tmpclasses/UnverifiableIntf.class + static byte[] makeUnverifiableIntf() throws Exception { + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V1_6, ACC_ABSTRACT + ACC_INTERFACE, "UnverifiableIntf", null, "java/lang/Object", null); + + { + fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "x", "LVerifierTest0;", null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "", "()V", null, null); + mv.visitCode(); + //WAS mv.visitTypeInsn(NEW, "VerifierTest"); + mv.visitTypeInsn(NEW, "java/lang/Object"); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, "VerifierTest0", "", "()V", false); + mv.visitFieldInsn(PUTSTATIC, "UnverifiableIntf", "x", "LVerifierTest0;"); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 0); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } + +} diff --git a/test/hotspot/jtreg/runtime/appcds/VerifierTest_0.java b/test/hotspot/jtreg/runtime/appcds/VerifierTest_0.java new file mode 100644 index 00000000000..6ed2f6d35d5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/VerifierTest_0.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, 2017, 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 Unverfiable app classes should not be archived. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules jdk.jartool/sun.tools.jar + * java.base/jdk.internal.org.objectweb.asm + * @compile test-classes/Greet.java + * @compile test-classes/Hi.java + * @compile test-classes/VerifierTest0.java + * @run main/othervm/timeout=3600 VerifierTest 0 + */ diff --git a/test/hotspot/jtreg/runtime/appcds/VerifierTest_1A.java b/test/hotspot/jtreg/runtime/appcds/VerifierTest_1A.java new file mode 100644 index 00000000000..8a5430e2263 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/VerifierTest_1A.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, 2017, 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 Unverfiable app classes should not be archived. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules jdk.jartool/sun.tools.jar + * java.base/jdk.internal.org.objectweb.asm + * @compile test-classes/Greet.java + * @compile test-classes/Hi.java + * @compile test-classes/VerifierTest0.java + * @run main/othervm/timeout=3600 VerifierTest 1A + */ diff --git a/test/hotspot/jtreg/runtime/appcds/VerifierTest_1B.java b/test/hotspot/jtreg/runtime/appcds/VerifierTest_1B.java new file mode 100644 index 00000000000..7a721d13ba8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/VerifierTest_1B.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, 2017, 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 Unverfiable app classes should not be archived. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules jdk.jartool/sun.tools.jar + * java.base/jdk.internal.org.objectweb.asm + * @compile test-classes/Greet.java + * @compile test-classes/Hi.java + * @compile test-classes/VerifierTest0.java + * @run main/othervm/timeout=3600 VerifierTest 1B + */ diff --git a/test/hotspot/jtreg/runtime/appcds/VerifierTest_2.java b/test/hotspot/jtreg/runtime/appcds/VerifierTest_2.java new file mode 100644 index 00000000000..c7bbe8793f7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/VerifierTest_2.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, 2017, 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 Unverfiable app classes should not be archived. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules jdk.jartool/sun.tools.jar + * java.base/jdk.internal.org.objectweb.asm + * @compile test-classes/Greet.java + * @compile test-classes/Hi.java + * @compile test-classes/VerifierTest0.java + * @run main/othervm/timeout=3600 VerifierTest 2 + */ diff --git a/test/hotspot/jtreg/runtime/appcds/WideIloadTest.java b/test/hotspot/jtreg/runtime/appcds/WideIloadTest.java new file mode 100644 index 00000000000..9323924449d --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/WideIloadTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 2017, 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 Test 'iload_w' bytecode in shared class + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Iloadw.jasm + * @compile test-classes/IloadwMain.java + * @run main WideIloadTest + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class WideIloadTest { + public static void main(String args[]) throws Exception { + JarBuilder.build("iload_w", "Iloadw", "IloadwMain"); + String appJar = TestCommon.getTestJar("iload_w.jar"); + OutputAnalyzer dumpOutput = TestCommon.dump(appJar, TestCommon.list( + "Iloadw", "IloadwMain")); + TestCommon.checkDump(dumpOutput); + OutputAnalyzer execOutput = TestCommon.exec(appJar, "IloadwMain"); + TestCommon.checkExec(execOutput, "Passed"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/WrongClasspath.java b/test/hotspot/jtreg/runtime/appcds/WrongClasspath.java new file mode 100644 index 00000000000..d3069c33cd9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/WrongClasspath.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, 2017, 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 classpath mismatch between dump time and execution time + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main WrongClasspath + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class WrongClasspath { + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + + // Dump an archive with a specified JAR file in -classpath + TestCommon.testDump(appJar, TestCommon.list("Hello")); + + // Then try to execute the archive without -classpath -- it should fail + OutputAnalyzer output = TestCommon.execCommon( + /* "-cp", appJar, */ // <- uncomment this and the execution should succeed + "Hello"); + output.shouldContain("Unable to use shared archive"); + output.shouldContain("shared class paths mismatch"); + output.shouldHaveExitValue(1); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/XShareAutoWithChangedJar.java b/test/hotspot/jtreg/runtime/appcds/XShareAutoWithChangedJar.java new file mode 100644 index 00000000000..d3c5c8ef50c --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/XShareAutoWithChangedJar.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, 2017, 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 Test -Xshare:auto for AppCDS + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run main XShareAutoWithChangedJar + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class XShareAutoWithChangedJar { + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.build("XShareAutoWithChangedJar", "Hello"); + + // 1. dump + OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("Hello")); + TestCommon.checkDump(output); + + // 2. change the jar + JarBuilder.build("XShareAutoWithChangedJar", "Hello"); + + // 3. exec + output = TestCommon.execAuto("-cp", appJar, "Hello"); + output.shouldContain("Hello World"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferences.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferences.java new file mode 100644 index 00000000000..6bd96c2abfd --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferences.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 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 Test resolved_references + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @compile CheckCachedResolvedReferencesApp.java + * @compile ../test-classes/Hello.java + * @run main ClassFileInstaller -jar app.jar CheckCachedResolvedReferencesApp + * @run main ClassFileInstaller -jar hello.jar Hello + * @run main ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox + * @run main CheckCachedResolvedReferences + */ + +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +public class CheckCachedResolvedReferences { + public static void main(String[] args) throws Exception { + String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + String appJar = ClassFileInstaller.getJarPath("app.jar"); + String helloJarPath = ClassFileInstaller.getJarPath("hello.jar"); + + String classlist[] = new String[] { + "CheckCachedResolvedReferencesApp", // built-in app loader + "java/lang/Object id: 1", // boot loader + "Hello id: 2 super: 1 source: " + helloJarPath // custom loader + }; + + TestCommon.testDump(appJar, classlist, use_whitebox_jar); + OutputAnalyzer output = TestCommon.exec(appJar, use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckCachedResolvedReferencesApp", + helloJarPath); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferencesApp.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferencesApp.java new file mode 100644 index 00000000000..0db69dd3391 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferencesApp.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import sun.hotspot.WhiteBox; + +public class CheckCachedResolvedReferencesApp { + public static void main(String args[]) throws Exception { + String path = args[0]; + URL url = new File(path).toURI().toURL(); + URL[] urls = new URL[] {url}; + + URLClassLoader loader = new URLClassLoader(urls); + Class hello = loader.loadClass("Hello"); + System.out.println("Loaded " + hello + " from " + url + " using loader " + loader); + + WhiteBox wb = WhiteBox.getWhiteBox(); + + if (!wb.areOpenArchiveHeapObjectsMapped()) { + System.out.println("Archived open_archive_heap objects are not mapped."); + System.out.println("This may happen during normal operation. Test Skipped."); + return; + } + + // CheckCachedResolvedReferencesApp is shared class and loaded by the + // AppClassLoader. It should have cached resolved_references. + if (wb.isSharedClass(CheckCachedResolvedReferencesApp.class)) { + Object refs1 = wb.getResolvedReferences(CheckCachedResolvedReferencesApp.class); + if (refs1 != null && wb.isShared(refs1)) { + System.out.println( + "resolved references from CheckCachedResolvedReferencesApp is cached"); + } else { + throw new RuntimeException( + "FAILED. CheckCachedResolvedReferencesApp has no cached resolved references"); + } + } + + // Hello is shared class and loaded by the 'loader' defined in current app. + // It should not have cached resolved_references. + if (wb.isSharedClass(hello)) { + Object refs2 = wb.getResolvedReferences(hello); + if (refs2 != null) { + if (!wb.isShared(refs2)) { + System.out.println("resolved references from hello is not cached"); + } else { + throw new RuntimeException( + "FAILED. Hello has unexpected cached resolved references"); + } + } else { + throw new RuntimeException("FAILED. Hello has no resolved references"); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/DumpTimeVerifyFailure.config.txt b/test/hotspot/jtreg/runtime/appcds/cacheObject/DumpTimeVerifyFailure.config.txt new file mode 100644 index 00000000000..fb6912f2c3c --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/DumpTimeVerifyFailure.config.txt @@ -0,0 +1,3 @@ +VERSION: 1.0 +@SECTION: String +26: shared_string_from_MyInner diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/DumpTimeVerifyFailure.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/DumpTimeVerifyFailure.java new file mode 100644 index 00000000000..12be0931edf --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/DumpTimeVerifyFailure.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, 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 Dump time should not crash if any class with shared strings fails verification due to missing dependencies. + * @bug 8186789 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @compile MyOuter.java MyException.java + * @run main DumpTimeVerifyFailure + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class DumpTimeVerifyFailure { + public static void main(String[] args) throws Exception { + // App classes (see MyOuter.java): + // MyOuter + // MyInnder$MyOuter extends MyOuter + // MyException + // + // MyOuter$MyInner.test() throws MyException. + // The missingMyException.jar file only includes MyOuter and + // MyOuter$MyInner classes, but not the MyException class. + // At dump time, MyOuter and MyOuter$MyInner classes fail + // verification due to missing MyException class. + String[] ARCHIVE_CLASSES = {"MyOuter", "MyOuter$MyInner"}; + String appJar = JarBuilder.build("missingMyException", ARCHIVE_CLASSES); + + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, ARCHIVE_CLASSES, + "-Xlog:verification", + "-XX:SharedArchiveConfigFile=" + TestCommon.getSourceFile("DumpTimeVerifyFailure.config.txt")); + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStress.config.txt b/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStress.config.txt new file mode 100644 index 00000000000..af3e33bb977 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStress.config.txt @@ -0,0 +1,3 @@ +VERSION: 1.0 +@SECTION: String +25: GCStressApp_shared_string diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStressApp.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStressApp.java new file mode 100644 index 00000000000..636da040d6b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStressApp.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.*; +import java.util.*; +import sun.hotspot.WhiteBox; + +// All strings in archived classes are shared +public class GCStressApp { + static WhiteBox wb = WhiteBox.getWhiteBox(); + static int[] arr; + + static String get_shared_string() { + String shared_str = "GCStressApp_shared_string"; + return shared_str; + } + + static String get_shared_string1() { + String shared_str1 = "GCStressApp_shared_string1"; + return shared_str1; + } + + static void allocAlot() { + try { + Random random = new Random(); + for (int i = 0; i < 1024 * 1024; i++) { + int len = random.nextInt(10000); + arr = new int[len]; + } + } catch (java.lang.OutOfMemoryError e) { } + } + + static void runGC() { + wb.fullGC(); + } + + public static void main(String args[]) throws Exception { + if (!wb.isSharedClass(GCStressApp.class)) { + System.out.println("GCStressApp is not shared. Possibly there was a mapping failure."); + return; + } + + if (wb.areSharedStringsIgnored()) { + System.out.println("Shared strings are ignored."); + return; + } + + Object refs = wb.getResolvedReferences(GCStressApp.class); + if (wb.isShared(refs)) { + String shared_str = get_shared_string(); + String shared_str1 = get_shared_string1(); + + if (!wb.isShared(shared_str)) { + throw new RuntimeException("FAILED. GCStressApp_shared_string is not shared"); + } + + if (!wb.isShared(shared_str1)) { + throw new RuntimeException("FAILED. GCStressApp_shared_string1 is not shared"); + } + + allocAlot(); + runGC(); + runGC(); + runGC(); + + System.out.println("Passed"); + } else { + System.out.println( + "No cached resolved references. Open archive heap data is not used."); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStressTest.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStressTest.java new file mode 100644 index 00000000000..591de9b3e67 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/GCStressTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @compile GCStressApp.java + * @run main ClassFileInstaller -jar gcstress.jar GCStressApp + * @run main ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox + * @run main GCStressTest + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class GCStressTest { + public static void main(String[] args) throws Exception { + String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + String appJar = ClassFileInstaller.getJarPath("gcstress.jar"); + String appClasses[] = TestCommon.list("GCStressApp"); + + OutputAnalyzer output = TestCommon.dump(appJar, appClasses, + use_whitebox_jar, + "-Xms20M", "-Xmx20M"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "-Xlog:cds=info", + "-Xms20M", "-Xmx20M", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI","GCStressApp"); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/InstrumentationAgent.mf b/test/hotspot/jtreg/runtime/appcds/cacheObject/InstrumentationAgent.mf new file mode 100644 index 00000000000..58dcf797de6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/InstrumentationAgent.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Premain-Class: InstrumentationRegisterClassFileTransformer +Agent-Class: InstrumentationRegisterClassFileTransformer +Can-Retransform-Classes: true +Can-Redefine-Classes: true diff --git a/src/hotspot/share/classfile/vmSymbols_ext.hpp b/test/hotspot/jtreg/runtime/appcds/cacheObject/MyException.java similarity index 79% rename from src/hotspot/share/classfile/vmSymbols_ext.hpp rename to test/hotspot/jtreg/runtime/appcds/cacheObject/MyException.java index 4b68d8f234b..39a464b4f00 100644 --- a/src/hotspot/share/classfile/vmSymbols_ext.hpp +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/MyException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,8 @@ * questions. * */ - -#ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP -#define SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP - -#define VM_SYMBOLS_DO_EXT(template, do_alias) - -#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP - +public class MyException extends Exception { + public MyException(String msg) { + super(msg); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/MyOuter.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/MyOuter.java new file mode 100644 index 00000000000..8773772ac68 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/MyOuter.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, 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. + * + */ +public class MyOuter { + public void exp() throws MyException { + throw new MyException("MyOuter exception"); + } + + public void test() throws Exception { + System.out.println("MyOuter"); + try { + exp(); + } catch (MyException e) { + } + } + + public static final class MyInner extends MyOuter { + static String myString = "shared_string_from_MyInner"; + public void test() { + System.out.println("MyInner"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/OpenArchiveRegion.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/OpenArchiveRegion.java new file mode 100644 index 00000000000..df1b348913f --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/OpenArchiveRegion.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, 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 Test open archive heap regions + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @compile ../test-classes/Hello.java + * @run main OpenArchiveRegion + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class OpenArchiveRegion { + public static void main(String[] args) throws Exception { + JarBuilder.getOrCreateHelloJar(); + String appJar = TestCommon.getTestJar("hello.jar"); + String appClasses[] = TestCommon.list("Hello"); + + // Dump with open archive heap region, requires G1 GC + OutputAnalyzer output = TestCommon.dump(appJar, appClasses); + TestCommon.checkDump(output, "oa0 space:"); + output.shouldNotContain("oa0 space: 0 ["); + output = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(output, "Hello World"); + output = TestCommon.exec(appJar, "-XX:+UseSerialGC", "Hello"); + TestCommon.checkExec(output, "Hello World"); + + // Dump with open archive heap region disabled when G1 GC is not in use + output = TestCommon.dump(appJar, appClasses, "-XX:+UseParallelGC"); + TestCommon.checkDump(output); + output.shouldNotContain("oa0 space:"); + output = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(output, "Hello World"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/RangeNotWithinHeap.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/RangeNotWithinHeap.java new file mode 100644 index 00000000000..13242f72f0b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/RangeNotWithinHeap.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 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 Shared classes can still be used when archived heap regions cannot be + * mapped due to out of range, and -Xshare:on should not fail. Test on + * linux 64-bit only since the HeapBaseMinAddress value is platform specific. + * The value used in the test may cause different behavior on other platforms. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (os.family == "linux") & (os.arch == "amd64") & (sun.arch.data.model == "64") + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @compile ../test-classes/Hello.java + * @run main RangeNotWithinHeap + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class RangeNotWithinHeap { + public static void main(String[] args) throws Exception { + JarBuilder.getOrCreateHelloJar(); + String appJar = TestCommon.getTestJar("hello.jar"); + String appClasses[] = TestCommon.list("Hello"); + + OutputAnalyzer output = TestCommon.dump(appJar, appClasses, + "-XX:HeapBaseMinAddress=0x600000000", "-Xmx6G", "-Xlog:gc+heap=trace"); + TestCommon.checkDump(output, "oa0 space:"); + + // Force archive region out of runtime java heap + output = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(output, "Hello World"); + output = TestCommon.exec(appJar, + "-XX:HeapBaseMinAddress=0x600000000", "-Xmx2G", "-Xlog:gc+heap=trace,cds", "Hello"); + TestCommon.checkExec(output, "Hello World"); + try { + output.shouldContain( + "UseSharedSpaces: Unable to allocate region, range is not within java heap."); + } catch (Exception e) { + // In rare case the heap data is not used. + if (output.getOutput().contains("Cached heap data from the CDS archive is being ignored")) { + return; + } + // Check for common shared class data mapping failures. + TestCommon.checkCommonExecExceptions(output, e); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassApp.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassApp.java new file mode 100644 index 00000000000..fa482e70a5e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassApp.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.instrument.ClassDefinition; +import java.lang.instrument.Instrumentation; +import java.lang.instrument.UnmodifiableClassException; +import java.net.URL; +import java.net.URLClassLoader; +import java.io.File; +import java.security.CodeSigner; +import java.security.CodeSource; +import java.security.ProtectionDomain; +import sun.hotspot.WhiteBox; + +public class RedefineClassApp { + static WhiteBox wb = WhiteBox.getWhiteBox(); + + public static interface Intf { // Loaded from Boot class loader (-Xbootclasspath/a). + public String get(); + } + public static class Bar implements Intf { // Loaded from Boot class loader. + public String get() { + return "buzz"; + } + } + public static class Foo implements Intf { // Loaded from AppClassLoader + public String get() { + return "buzz"; + } + } + + static int numTests = 0; + static int failed = 0; + static Instrumentation instrumentation; + + public static void main(String args[]) throws Throwable { + if (wb.areSharedStringsIgnored()) { + System.out.println("Shared strings are ignored."); + return; + } + + File bootJar = new File(args[0]); + File appJar = new File(args[1]); + + instrumentation = InstrumentationRegisterClassFileTransformer.getInstrumentation(); + System.out.println("INFO: instrumentation = " + instrumentation); + + testBootstrapCDS("Bootstrap Loader", bootJar); + testAppCDSv1("Application Loader", appJar); + + if (failed > 0) { + throw new RuntimeException("FINAL RESULT: " + failed + " out of " + numTests + " test case(s) have failed"); + } else { + System.out.println("FINAL RESULT: All " + numTests + " test case(s) have passed!"); + } + + // Full GC. The cached objects in adjustable archive heap regions are + // scanned. The archive regions are verified. No error should be + // reported. + wb.fullGC(); + } + + static void testBootstrapCDS(String group, File jar) throws Throwable { + doTest(group, new Bar(), jar); + } + + static void testAppCDSv1(String group, File jar) throws Throwable { + doTest(group, new Foo(), jar); + } + + static void doTest(String group, Intf object, File jar) throws Throwable { + numTests ++; + + Class klass = object.getClass(); + System.out.println(); + System.out.println("++++++++++++++++++++++++++"); + System.out.println("Test group: " + group); + System.out.println("Testing with classloader = " + klass.getClassLoader()); + System.out.println("Testing with class = " + klass); + System.out.println("Test is shared = " + wb.isSharedClass(klass)); + System.out.println("++++++++++++++++++++++++++"); + + // Call get() before redefine. All strings in archived classes are shared. + String res = object.get(); + System.out.println("get() returns " + res); + if (res.equals("buzz") && wb.isShared(res)) { + System.out.println("get() returns " + res + ", string is shared"); + } else { + if (!res.equals("buzz")) { + System.out.println("FAILED. buzz is expected but got " + res); + } else { + System.out.println("FAILED. " + res + " is not shared"); + } + failed ++; + return; + } + res = null; // release the local reference to the string + + // Run GC + System.gc(); + System.gc(); + System.gc(); + + // Redefine the shared class + byte[] buff = Util.getClassFileFromJar(jar, klass.getName()); + Util.replace(buff, "buzz", "huzz"); + String f = "(failed)"; + try { + instrumentation.redefineClasses(new ClassDefinition(klass, buff)); + f = object.get(); + } catch (UnmodifiableClassException|UnsupportedOperationException e) { + e.printStackTrace(); + } + if (f.equals("huzz")) { + System.out.println("PASSED: object.get() after redefinition returns " + f); + } else { + System.out.println("FAILED: object.get() after redefinition returns " + f); + failed ++; + } + + // Run GC. Should not crash. + System.gc(); + System.gc(); + System.gc(); + + System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++ (done)\n\n"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassTest.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassTest.java new file mode 100644 index 00000000000..bfcd82f5742 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017, 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 Redefine shared class. GC should not cause crash with cached resolved_references. + * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes /test/hotspot/jtreg/runtime/appcds/jvmti + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @requires vm.flavor != "minimal" + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * java.management + * @build sun.hotspot.WhiteBox + * RedefineClassApp + * InstrumentationClassFileTransformer + * InstrumentationRegisterClassFileTransformer + * @run main/othervm RedefineClassTest + */ + +import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.VirtualMachineDescriptor; +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import jdk.test.lib.Asserts; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class RedefineClassTest { + public static String bootClasses[] = { + "RedefineClassApp$Intf", + "RedefineClassApp$Bar", + "sun.hotspot.WhiteBox", + }; + public static String appClasses[] = { + "RedefineClassApp", + "RedefineClassApp$Foo", + }; + public static String sharedClasses[] = TestCommon.concat(bootClasses, appClasses); + + public static String agentClasses[] = { + "InstrumentationClassFileTransformer", + "InstrumentationRegisterClassFileTransformer", + "Util", + }; + + public static void main(String[] args) throws Throwable { + runTest(); + } + + public static void runTest() throws Throwable { + String bootJar = + ClassFileInstaller.writeJar("RedefineClassBoot.jar", bootClasses); + String appJar = + ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses); + String agentJar = + ClassFileInstaller.writeJar("InstrumentationAgent.jar", + ClassFileInstaller.Manifest.fromSourceFile("InstrumentationAgent.mf"), + agentClasses); + + String bootCP = "-Xbootclasspath/a:" + bootJar; + + String agentCmdArg; + agentCmdArg = "-javaagent:" + agentJar; + + TestCommon.testDump(appJar, sharedClasses, bootCP, "-Xlog:gc+region=trace"); + + OutputAnalyzer out = TestCommon.execAuto("-cp", appJar, + bootCP, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xlog:gc+region=trace,cds=info", + agentCmdArg, + "RedefineClassApp", bootJar, appJar); + out.reportDiagnosticSummary(); + + CDSOptions opts = (new CDSOptions()).setXShareMode("auto"); + TestCommon.checkExec(out, opts); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatA.java b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatA.java new file mode 100644 index 00000000000..65c4d846499 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatA.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2015, 2017, 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 Tests the format checking of class list format. + * + * (NOTE: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java + * test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java + * @run main ClassListFormatA + */ + +public class ClassListFormatA extends ClassListFormatBase { + static { + // Uncomment the following line to run only one of the test cases + // ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE A1"; + } + + public static void main(String[] args) throws Throwable { + String appJar = JarBuilder.getOrCreateHelloJar(); + String customJarPath = JarBuilder.build("ClassListFormatA", "CustomLoadee", + "CustomLoadee2", "CustomInterface2_ia", "CustomInterface2_ib"); + //---------------------------------------------------------------------- + // TESTGROUP A: general bad input + //---------------------------------------------------------------------- + dumpShouldFail( + "TESTCASE A1: bad input - interface: instead of interfaces:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee interface: 1" + ), + "Unknown input:"); + + dumpShouldFail( + "TESTCASE A2: bad input - negative IDs not allowed", + appJar, classlist( + "Hello", + "java/lang/Object id: -1" + ), + "Error: negative integers not allowed"); + + dumpShouldFail( + "TESTCASE A3: bad input - bad ID (not an integer)", + appJar, classlist( + "Hello", + "java/lang/Object id: xyz" + ), + "Error: expected integer"); + + if (false) { + // FIXME - classFileParser.cpp needs fixing. + dumpShouldFail( + "TESTCASE A4: bad input - bad ID (integer too big)", + appJar, classlist( + "Hello", + "java/lang/Object id: 2147483648" // <- this is 0x80000000 + ), + "Error: expected integer"); + + // FIXME + dumpShouldFail( + "TESTCASE A5: bad input - bad ID (integer too big)", + appJar, classlist( + "Hello", + "java/lang/Object id: 21474836489" // bigger than 32-bit! + ), + "Error: expected integer"); + } + + // Good input: + dumpShouldPass( + "TESTCASE A6: extraneous spaces, tab characters and trailing new line characters", + appJar, classlist( + "Hello ", // trailing spaces + "java/lang/Object\tid:\t1", // \t instead of ' ' + "CustomLoadee id: 2 super: 1 source: " + customJarPath, + "CustomInterface2_ia id: 3 super: 1 source: " + customJarPath + " ", + "CustomInterface2_ib id: 4 super: 1 source: " + customJarPath + "\t\t\r" , + "CustomLoadee2 id: 5 super: 1 interfaces: 3 4 source: " + customJarPath // preceding spaces + )); + + int _max_allowed_line = 4096; // Must match ClassListParser::_max_allowed_line in C code. + int _line_buf_extra = 10; // Must match ClassListParser::_line_buf_extra in C code. + StringBuffer sbuf = new StringBuffer(); + for (int i=0; i<_max_allowed_line+1; i++) { + sbuf.append("x"); + } + + dumpShouldFail( + "TESTCASE A7: bad input - line too long", + appJar, classlist( + sbuf.toString() + ), + "input line too long (must be no longer than " + _max_allowed_line + " chars"); + + for (int i=0; i<_line_buf_extra + 1000; i++) { + sbuf.append("X"); + } + + dumpShouldFail( + "TESTCASE A8: bad input - line too long: try to overflow C buffer", + appJar, classlist( + sbuf.toString() + ), + "input line too long (must be no longer than " + _max_allowed_line + " chars"); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatB.java b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatB.java new file mode 100644 index 00000000000..6ae1488d125 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatB.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, 2017, 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 Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp. + * + * (NOTE: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java + * test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java + * @run main ClassListFormatB + */ + +public class ClassListFormatB extends ClassListFormatBase { + static { + // Uncomment the following line to run only one of the test cases + // ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE B1"; + } + + public static void main(String[] args) throws Throwable { + String appJar = JarBuilder.getOrCreateHelloJar(); + String customJarPath = JarBuilder.build("ClassListFormatB", "CustomLoadee", + "CustomLoadee2", "CustomInterface2_ia", "CustomInterface2_ib"); + //---------------------------------------------------------------------- + // TESTGROUP B if source IS specified + //---------------------------------------------------------------------- + dumpShouldFail( + "TESTCASE B1: if source: is specified, must specify super:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee id: 2 source: " + customJarPath + ), + "If source location is specified, super class must be also specified"); + + dumpShouldFail( + "TESTCASE B2: if source: is specified, must specify id:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee super: 1 source: " + customJarPath + ), + "If source location is specified, id must be also specified"); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatBase.java b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatBase.java new file mode 100644 index 00000000000..7b1301c0137 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatBase.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import jdk.test.lib.process.OutputAnalyzer; + +/** + * Base class for ClassListFormat[A,B,C...].java + */ +public class ClassListFormatBase { + protected static String RUN_ONLY_TEST = null; + + static void dumpShouldFail(String caseHelp, String appJar, String[] appClasses, + String... expected_errors) throws Throwable { + if (RUN_ONLY_TEST != null && !caseHelp.startsWith(RUN_ONLY_TEST)) { + System.out.println("Skipped via RUN_ONLY_TEST: " + caseHelp); + return; + } + System.out.println("------------------------------"); + System.out.println(caseHelp); + System.out.println("------------------------------"); + + try { + OutputAnalyzer output = TestCommon.dump(appJar, appClasses); + output.shouldHaveExitValue(1); + for (String s : expected_errors) { + output.shouldContain(s); + } + } catch (Throwable t) { + System.out.println("FAILED CASE: " + caseHelp); + throw t; + } + } + + static void dumpShouldPass(String caseHelp, String appJar, String[] appClasses, + String... expected_msgs) throws Throwable { + if (RUN_ONLY_TEST != null && !caseHelp.startsWith(RUN_ONLY_TEST)) { + System.out.println("Skipped via RUN_ONLY_TEST: " + caseHelp); + return; + } + System.out.println("------------------------------"); + System.out.println(caseHelp); + System.out.println("------------------------------"); + + try { + OutputAnalyzer output = TestCommon.dump(appJar, appClasses); + output.shouldHaveExitValue(0); + output.shouldContain("Dumping"); + for (String s : expected_msgs) { + output.shouldContain(s); + } + } catch (Throwable t) { + System.out.println("FAILED CASE: " + caseHelp); + throw t; + } + } + + static String[] classlist(String... args) { + return TestCommon.list(args); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatC.java b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatC.java new file mode 100644 index 00000000000..ff4dd11eb1e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatC.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, 2017, 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 Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp. + * + * (NOTE: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java + * test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java + * @run main ClassListFormatC + */ + +public class ClassListFormatC extends ClassListFormatBase { + static { + // Uncomment the following line to run only one of the test cases + // ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE C1"; + } + + public static void main(String[] args) throws Throwable { + String appJar = JarBuilder.getOrCreateHelloJar(); + String customJarPath = JarBuilder.build("ClassListFormatC", "CustomLoadee", + "CustomLoadee2", "CustomInterface2_ia", + "CustomInterface2_ib"); + + //---------------------------------------------------------------------- + // TESTGROUP C: if source IS NOT specified + //---------------------------------------------------------------------- + dumpShouldFail( + "TESTCASE C1: if source: is NOT specified, must NOT specify super:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee super: 1" + ), + "If source location is not specified, super class must not be specified"); + + dumpShouldFail( + "TESTCASE C2: if source: is NOT specified, must NOT specify interface:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee interfaces: 1" + ), + "If source location is not specified, interface(s) must not be specified"); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatD.java b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatD.java new file mode 100644 index 00000000000..0a911d6750e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatD.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, 2017, 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 Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp. + * + * (NOTE: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java + * test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java + * @run main ClassListFormatD + */ + +public class ClassListFormatD extends ClassListFormatBase { + static { + // Uncomment the following line to run only one of the test cases + // ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE D1"; + } + + public static void main(String[] args) throws Throwable { + String appJar = JarBuilder.getOrCreateHelloJar(); + String customJarPath = JarBuilder.build("ClassListFormatD", "CustomLoadee", + "CustomLoadee2", "CustomInterface2_ia", + "CustomInterface2_ib"); + + //---------------------------------------------------------------------- + // TESTGROUP D: bad use of IDs + //---------------------------------------------------------------------- + dumpShouldFail( + "TESTCASE D1: duplicated id:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee id: 1 super: 1 source: " + customJarPath + ), + "Duplicated ID 1 for class CustomLoadee"); + + dumpShouldFail( + "TESTCASE D2: bad ID for super:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee id: 2 super: 2 source: " + customJarPath + ), + "Super class id 2 is not yet loaded"); + + dumpShouldFail( + "TESTCASE D3: bad ID in interfaces:", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee id: 2 super: 1 interfaces: 2 source: " + customJarPath + ), + "Interface id 2 is not yet loaded"); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatE.java b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatE.java new file mode 100644 index 00000000000..b61e08459b6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatE.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015, 2017, 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 Tests the format checking of hotspot/src/closed/share/vm/classfile/classListParser.cpp. + * + * (NOTE: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java test-classes/CustomLoadee.java test-classes/CustomLoadee2.java + * test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java + * @run main ClassListFormatE + */ + +public class ClassListFormatE extends ClassListFormatBase { + static { + // Uncomment the following line to run only one of the test cases + // ClassListFormatBase.RUN_ONLY_TEST = "TESTCASE E1"; + } + + public static void main(String[] args) throws Throwable { + String appJar = JarBuilder.getOrCreateHelloJar(); + String customJarPath = JarBuilder.build("ClassListFormatE", "CustomLoadee", + "CustomLoadee2", "CustomInterface2_ia", + "CustomInterface2_ib"); + + //---------------------------------------------------------------------- + // TESTGROUP E: super class and interfaces + //---------------------------------------------------------------------- + dumpShouldFail( + "TESTCASE E1: missing interfaces: keyword", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomLoadee2 id: 1 super: 1 source: " + customJarPath + ), + "Class CustomLoadee2 implements the interface CustomInterface2_ia, but no interface has been specified in the input line"); + + dumpShouldFail( + "TESTCASE E2: missing one interface", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomInterface2_ia id: 2 super: 1 source: " + customJarPath, + "CustomInterface2_ib id: 3 super: 1 source: " + customJarPath, + "CustomLoadee2 id: 4 super: 1 interfaces: 2 source: " + customJarPath + ), + "The interface CustomInterface2_ib implemented by class CustomLoadee2 does not match any of the specified interface IDs"); + + dumpShouldFail( + "TESTCASE E3: specifying an interface that's not implemented by the class", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomInterface2_ia id: 2 super: 1 source: " + customJarPath, + "CustomLoadee id: 2 super: 1 interfaces: 2 source: " + customJarPath + ), + "The number of interfaces (1) specified in class list does not match the class file (0)"); + + dumpShouldFail( + "TESTCASE E4: repeating an ID in the interfaces: keyword", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomInterface2_ia id: 2 super: 1 source: " + customJarPath, + "CustomInterface2_ib id: 3 super: 1 source: " + customJarPath, + "CustomLoadee2 id: 4 super: 1 interfaces: 2 2 3 source: " + customJarPath + ), + "The number of interfaces (3) specified in class list does not match the class file (2)"); + + dumpShouldFail( + "TESTCASE E5: wrong super class", + appJar, classlist( + "Hello", + "java/lang/Object id: 1", + "CustomInterface2_ia id: 2 super: 1 source: " + customJarPath, + "CustomInterface2_ib id: 3 super: 1 source: " + customJarPath, + "CustomLoadee id: 4 super: 1 source: " + customJarPath, + "CustomLoadee2 id: 5 super: 4 interfaces: 2 3 source: " + customJarPath + ), + "The specified super class CustomLoadee (id 4) does not match actual super class java.lang.Object"); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/CustomLoaderApp.java b/test/hotspot/jtreg/runtime/appcds/customLoader/CustomLoaderApp.java new file mode 100644 index 00000000000..0075529e8f5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/CustomLoaderApp.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, 2017, 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. + * + */ + +// This is a utlitity test class for loading classes-under-test +// by means of custom class loader. +// See AppCDS/jvmti/transformRelatedClasses/TransformRelatedClasses.java +// for an example. +// Use this test app in conjunction with other tests +// to load and exercise classes using custom class loader(s). +// This class is intended to be called by the "main test driver" +// inside a child process, normally with sharing enabled. +// +// Arguments: customJarPath, loaderType, testClass +// customJarPath - a path to jar file containing classes for +// loading via this custom class loader, including the +// testClass +// loaderType - Currently only "unregistered" +// (Fingerprint verification method) is allowed +// testClass - the class to be loader; the test method with +// signature 'public static void test()' will be called +// on this class, so class must contain such method + + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.logging.Logger; + +public class CustomLoaderApp { + public static void ping() {}; + + private static void log(String msg) { + System.out.println("CustomLoaderApp: " + msg); + } + + public static void main(String[] args) throws Exception { + String path = args[0]; + URL url = new File(path).toURI().toURL(); + URL[] urls = new URL[] {url}; + + String loaderType = args[1]; + log("loaderType = " + loaderType); + + String testClass = args[2]; + log("testClass = " + testClass); + + switch(loaderType) { + case "unregistered": + loadAndUseWithUnregisteredLoader(urls, testClass); + break; + default: + throw new IllegalArgumentException("loader type is wrong: " + loaderType); + } + } + + + // Load the test classes using unregistered loader + // (i.e. loader that is not using AppCDS API) + private static void loadAndUseWithUnregisteredLoader(URL[] urls, String testClass) + throws Exception { + URLClassLoader urlClassLoader = new URLClassLoader(urls); + callTestMethod(loadAndCheck(urlClassLoader, testClass)); + } + + private static Class loadAndCheck(ClassLoader loader, String className) + throws ClassNotFoundException { + Class c = loader.loadClass(className); + log("class =" + c); + log("loader = " + c.getClassLoader()); + + // Check that c is defined by the correct loader + if (c.getClassLoader() != loader) { + String msg = String.format("c.getClassLoader() equals to <%s>, expected <%s>", + c.getClassLoader(), loader); + throw new RuntimeException(msg); + } + return c; + } + + private static void callTestMethod(Class c) throws Exception { + Method[] methods = c.getDeclaredMethods(); + for (Method m : methods) { + log("method = " + m.getName()); + if (m.getName().equals("test")) + m.invoke(null); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/HelloCustom.java b/test/hotspot/jtreg/runtime/appcds/customLoader/HelloCustom.java new file mode 100644 index 00000000000..750a251f178 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/HelloCustom.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, 2017, 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 Hello World test for AppCDS custom loader support + * (NOTE: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * @compile test-classes/Hello.java test-classes/CustomLoadee.java + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller -jar hello.jar Hello + * @run main ClassFileInstaller -jar hello_custom.jar CustomLoadee + * @run main ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox + * @run main HelloCustom + */ + +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +public class HelloCustom { + public static void main(String[] args) throws Exception { + String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + String appJar = ClassFileInstaller.getJarPath("hello.jar"); + String customJarPath = ClassFileInstaller.getJarPath("hello_custom.jar"); + + // Dump the archive + String classlist[] = new String[] { + "Hello", + "java/lang/Object id: 1", + "CustomLoadee id: 2 super: 1 source: " + customJarPath + }; + + OutputAnalyzer output; + TestCommon.testDump(appJar, classlist, + // command-line arguments ... + use_whitebox_jar); + + output = TestCommon.exec(appJar, + // command-line arguments ... + use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "Hello", customJarPath); + TestCommon.checkExec(output); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/LoaderSegregationTest.java b/test/hotspot/jtreg/runtime/appcds/customLoader/LoaderSegregationTest.java new file mode 100644 index 00000000000..f7d6b7bdcf0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/LoaderSegregationTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015, 2017, 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 Check that during dumping, the classes for BOOT/EXT/APP loaders are segregated from the + * custom loader classes. + * (NOTE: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.cds.custom.loaders + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/LoaderSegregation.java + * test-classes/CustomLoadee.java test-classes/CustomLoadee2.java + * test-classes/CustomInterface2_ia.java test-classes/CustomInterface2_ib.java + * test-classes/CustomLoadee3.java test-classes/CustomLoadee3Child.java + * test-classes/OnlyBuiltin.java + * test-classes/OnlyUnregistered.java + * ../test-classes/Util.java + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main LoaderSegregationTest + */ + +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +/** + * See "Handling of the classes in the AppCDS archive" at the top of + * systemDicrionatyShared.hpp. + * + * This test ensure that the 2 types of archived classes (BUILTIN and UNREGISTERED) + * are segregated at both dump-time and run time: + * + * [A] An archived BUILTIN class cannot be a subclass of a non-BUILTIN class. + * [B] An archived BUILTIN class cannot implement a non-BUILTIN interface. + * [C] BUILTIN and UNREGISTERED classes can be loaded only by their corresponding + * type of loaders. + * + */ +public class LoaderSegregationTest { + public static void main(String[] args) throws Exception { + String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + String appJar = JarBuilder.build("LoaderSegregation_app", "LoaderSegregation", + "CustomLoadee", "CustomLoadee2", "CustomLoadee3Child", "CustomInterface2_ia", + "OnlyBuiltin", "Util"); + + String app2Jar = JarBuilder.build("LoaderSegregation_app2", "CustomLoadee3", "CustomInterface2_ib"); + + String customJarPath = JarBuilder.build("LoaderSegregation_custom", "CustomLoadee", + "CustomLoadee2", "CustomInterface2_ia", "CustomInterface2_ib", + "CustomLoadee3", "CustomLoadee3Child", + "OnlyBuiltin", "OnlyUnregistered"); + + // Dump the archive + String classlist[] = new String[] { + "LoaderSegregation", + "java/lang/Object id: 1", + + // These are the UNREGISTERED classes: they have "source:" + // but they don't have "loader:". + "CustomLoadee id: 2 super: 1 source: " + customJarPath, + + "CustomInterface2_ia id: 3 super: 1 source: " + customJarPath, + "CustomInterface2_ib id: 4 super: 1 source: " + customJarPath, + "CustomLoadee2 id: 5 super: 1 interfaces: 3 4 source: " + customJarPath, + + "CustomLoadee3 id: 6 super: 1 source: " + customJarPath, + "CustomLoadee3Child id: 7 super: 6 source: " + customJarPath, + + // At dump time, the following BUILTIN classes are loaded after the UNREGISTERED + // classes from above. However, at dump time, they cannot use the UNREGISTERED classes are their + // super or interface. + "CustomLoadee", // can be loaded at dump time + "CustomLoadee2", // cannot be loaded at dump time (interface missing) + "CustomLoadee3Child", // cannot be loaded at dump time (super missing) + + // Check that BUILTIN and UNREGISTERED classes can be loaded only by their + // corresponding type of loaders. + "OnlyBuiltin", + "OnlyUnregistered id: 9 super: 1 source: " + customJarPath, + }; + + OutputAnalyzer output; + TestCommon.testDump(appJar, classlist, + // command-line arguments ... + use_whitebox_jar); + + output = TestCommon.exec(TestCommon.concatPaths(appJar, app2Jar), + // command-line arguments ... + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.security=ALL-UNNAMED", + use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "LoaderSegregation", customJarPath); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/customLoader/ParallelTestBase.java b/test/hotspot/jtreg/runtime/appcds/customLoader/ParallelTestBase.java new file mode 100644 index 00000000000..a536d831a27 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ParallelTestBase.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import jdk.test.lib.process.OutputAnalyzer; + +/* + * This is a base class for the following test cases: + * ParallelTestMultiFP.java + * ParallelTestSingleFP.java + */ +public class ParallelTestBase { + public static final int MAX_CLASSES = 40; // must match ../test-classes/ParallelLoad.java + public static int NUM_THREADS = 4; // must match ../test-classes/ParallelLoad.java + + public static final int SINGLE_CUSTOM_LOADER = 1; + public static final int MULTI_CUSTOM_LOADER = 2; + + public static final int FINGERPRINT_MODE = 1; + + public static void run(String[] args, int loaderType, int mode) throws Exception { + String[] cust_classes = new String[MAX_CLASSES]; + String[] cust_list; + + if (mode == FINGERPRINT_MODE) { + cust_list = new String[MAX_CLASSES]; + } else { + cust_list = new String[MAX_CLASSES * NUM_THREADS]; + } + + for (int i = 0; i argsList = new ArrayList(); + argsList.add("-XX:+UnlockDiagnosticVMOptions"); + argsList.add("-XX:+WhiteBoxAPI"); + argsList.add("-cp"); + argsList.add(appJar); + argsList.add(bootClassPath); + argsList.add("-verbose:class"); + argsList.add("ArrayTestHelper"); + // the following are input args to the ArrayTestHelper. + for (int i = 0; i < arrayClasses.length; i++) { + argsList.add(arrayClasses[i]); + } + String[] opts = new String[argsList.size()]; + opts = argsList.toArray(opts); + OutputAnalyzer output = TestCommon.execCommon(opts); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/javaldr/ArrayTestHelper.java b/test/hotspot/jtreg/runtime/appcds/javaldr/ArrayTestHelper.java new file mode 100644 index 00000000000..614f47e6546 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/javaldr/ArrayTestHelper.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class ArrayTestHelper { + public static void main(String[] args) throws Throwable { + + // load the classes one by one and ensure each one is from + // the shared archive + for (int i = 0; i < args.length; i++) { + + String cn = args[i].replace('/', '.'); + Class cls = Class.forName(cn); + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (wb.isSharedClass(cls)) { + System.out.println("As expected, " + args[i] + " is in shared space."); + } else { + throw new java.lang.RuntimeException(args[i] + " is not in shared space."); + } + } + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/javaldr/CheckAnonymousClass.java b/test/hotspot/jtreg/runtime/appcds/javaldr/CheckAnonymousClass.java new file mode 100644 index 00000000000..804c480cd74 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/javaldr/CheckAnonymousClass.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 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 ensure no anonymous class is being dumped into the CDS archive + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.jartool/sun.tools.jar + * @compile ../test-classes/Hello.java + * @run main CheckAnonymousClass + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class CheckAnonymousClass { + + public static void main(String[] args) throws Exception { + JarBuilder.build("hello", "Hello"); + + String appJar = TestCommon.getTestJar("hello.jar"); + + TestCommon.dump(appJar, TestCommon.list("Hello", "org/omg/CORBA/ORB"), + "--add-modules", "java.corba", "-Xlog:class+load=info"); + + OutputAnalyzer output = TestCommon.execCommon("-XX:+UnlockDiagnosticVMOptions", + "-cp", appJar, "-Xlog:class+load=info", "--add-modules", "java.corba", "Hello"); + + String prefix = ".class.load. "; + // class name pattern like the following: + // jdk.internal.loader.BuiltinClassLoader$$Lambda$1/1816757085 + // java.lang.invoke.LambdaForm$MH/1585787493 + String class_pattern = ".*Lambda([a-z0-9$]+)/([0-9]+).*"; + String suffix = ".*source: shared objects file.*"; + String pattern = prefix + class_pattern + suffix; + // during run time, anonymous classes shouldn't be loaded from the archive + try { + output.shouldNotMatch(pattern); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + + // inspect the archive and make sure no anonymous class is in there + output = TestCommon.execCommon("-XX:+UnlockDiagnosticVMOptions", + "-cp", appJar, "-Xlog:class+load=info", "-XX:+PrintSharedArchiveAndExit", + "-XX:+PrintSharedDictionary", "--add-modules", "java.corba", "Hello"); + try { + output.shouldNotMatch(class_pattern); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDump.java b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDump.java new file mode 100644 index 00000000000..22a7dad0a6d --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDump.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017, 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 When dumping the CDS archive, try to cause garbage collection while classes are being loaded. + * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.flavor != "minimal" + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * java.management + * @build GCDuringDumpTransformer Hello + * @run main/othervm GCDuringDump + */ + +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class GCDuringDump { + public static String appClasses[] = { + "Hello", + }; + public static String agentClasses[] = { + "GCDuringDumpTransformer", + }; + + public static void main(String[] args) throws Throwable { + String agentJar = + ClassFileInstaller.writeJar("GCDuringDumpTransformer.jar", + ClassFileInstaller.Manifest.fromSourceFile("GCDuringDumpTransformer.mf"), + agentClasses); + + String appJar = + ClassFileInstaller.writeJar("GCDuringDumpApp.jar", appClasses); + + String gcLog = "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug"; + + for (int i=0; i<2; i++) { + // i = 0 -- run without agent = no extra GCs + // i = 1 -- run with agent = cause extra GCs + + String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar; + + TestCommon.testDump(appJar, TestCommon.list("Hello"), + extraArg, "-Xmx32m", gcLog); + + OutputAnalyzer output = TestCommon.execCommon( + "-cp", appJar, + "-Xmx32m", + "-XX:+PrintSharedSpaces", + gcLog, + "Hello"); + TestCommon.checkExec(output); + } + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.java b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.java new file mode 100644 index 00000000000..bbde62429c4 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.Instrumentation; +import java.lang.instrument.IllegalClassFormatException; +import java.security.ProtectionDomain; + +public class GCDuringDumpTransformer implements ClassFileTransformer { + static int n = 0; + public byte[] transform(ClassLoader loader, String name, Class classBeingRedefined, + ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException { + n++; + + System.out.println("dump time loading: " + name + " in loader: " + loader); + System.out.println("making garbage: " + n); + try { + makeGarbage(); + } catch (Throwable t) { + t.printStackTrace(); + try { + Thread.sleep(200); // let GC to have a chance to run + } catch (Throwable t2) {} + } + System.out.println("making garbage: done"); + + return null; + } + + private static Instrumentation savedInstrumentation; + + public static void premain(String agentArguments, Instrumentation instrumentation) { + System.out.println("ClassFileTransformer.premain() is called"); + instrumentation.addTransformer(new GCDuringDumpTransformer(), /*canRetransform=*/true); + savedInstrumentation = instrumentation; + } + + public static Instrumentation getInstrumentation() { + return savedInstrumentation; + } + + public static void agentmain(String args, Instrumentation inst) throws Exception { + premain(args, inst); + } + + public static void makeGarbage() { + for (int x=0; x<10; x++) { + Object[] a = new Object[10000]; + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.mf b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.mf new file mode 100644 index 00000000000..8b44e6e9801 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Premain-Class: GCDuringDumpTransformer +Agent-Class: GCDuringDumpTransformer +Can-Retransform-Classes: true +Can-Redefine-Classes: true diff --git a/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDump.java b/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDump.java new file mode 100644 index 00000000000..38e23c31a30 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDump.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, 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 Similar to GCDuringDumping.java, this test adds the -XX:SharedArchiveConfigFile + * option for testing the interaction with GC and shared strings. + * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.flavor != "minimal" + * @requires vm.gc.G1 + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * java.management + * @build sun.hotspot.WhiteBox GCDuringDumpTransformer GCSharedStringsDuringDumpWb + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm/timeout=480 GCSharedStringsDuringDump + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import sun.hotspot.WhiteBox; + +public class GCSharedStringsDuringDump { + public static String appClasses[] = { + "GCSharedStringsDuringDumpWb", + }; + public static String agentClasses[] = { + "GCDuringDumpTransformer", + }; + + public static void main(String[] args) throws Throwable { + String agentJar = + ClassFileInstaller.writeJar("GCDuringDumpTransformer.jar", + ClassFileInstaller.Manifest.fromSourceFile("GCDuringDumpTransformer.mf"), + agentClasses); + + String appJar = + ClassFileInstaller.writeJar("GCSharedStringsDuringDumpApp.jar", appClasses); + + String gcLog = "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug"; + + String sharedArchiveCfgFile = + System.getProperty("user.dir") + File.separator + "GCSharedStringDuringDump_gen.txt"; + try (FileOutputStream fos = new FileOutputStream(sharedArchiveCfgFile)) { + PrintWriter out = new PrintWriter(new OutputStreamWriter(fos)); + out.println("VERSION: 1.0"); + out.println("@SECTION: String"); + out.println("31: shared_test_string_unique_14325"); + for (int i=0; i<100000; i++) { + String s = "generated_string " + i; + out.println(s.length() + ": " + s); + } + out.close(); + } + + JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + String whiteBoxJar = TestCommon.getTestJar("WhiteBox.jar"); + String bootClassPath = "-Xbootclasspath/a:" + whiteBoxJar; + + for (int i=0; i<2; i++) { + // i = 0 -- run without agent = no extra GCs + // i = 1 -- run with agent = cause extra GCs + + String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar; + + OutputAnalyzer output = TestCommon.dump( + appJar, TestCommon.list("GCSharedStringsDuringDumpWb"), + bootClassPath, extraArg, "-Xmx32m", gcLog, + "-XX:+UseCompressedOops", "-XX:+UseG1GC", + "-XX:SharedReadOnlySize=30m", + "-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile); + + if (output.getStdout().contains("Too many string space regions") || + output.getStderr().contains("Unable to write archive heap memory regions") || + output.getStdout().contains("Try increasing NewSize") || + output.getExitValue() != 0) { + // Try again with larger heap and NewSize, this should increase the + // G1 heap region size to 2M + TestCommon.testDump( + appJar, TestCommon.list("GCSharedStringsDuringDumpWb"), + bootClassPath, extraArg, "-Xmx8g", "-XX:NewSize=8m", gcLog, + "-XX:+UseCompressedOops", "-XX:+UseG1GC", + "-XX:SharedReadOnlySize=30m", + "-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile); + } + + output = TestCommon.execCommon( + "-cp", appJar, + bootClassPath, + "-Xmx32m", + "-XX:+PrintSharedSpaces", + "-XX:+UseCompressedOops", + "-XX:+UseG1GC", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:SharedReadOnlySize=30m", + gcLog, + "GCSharedStringsDuringDumpWb"); + TestCommon.checkExec(output); + } + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDumpWb.java b/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDumpWb.java new file mode 100644 index 00000000000..3fcebe5f5ed --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDumpWb.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class GCSharedStringsDuringDumpWb { + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + String s = "shared_test_string_unique_14325"; + s = s.intern(); + CheckString(wb, s); + for (int i=0; i<100000; i++) { + s = "generated_string " + i; + s = s.intern(); + CheckString(wb, s); + } + } + + public static void CheckString(WhiteBox wb, String s) { + if (!wb.areSharedStringsIgnored() && !wb.isShared(s)) { + throw new RuntimeException("String is not shared."); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java new file mode 100644 index 00000000000..99efbcbf135 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, 2017, 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 Abort dumping if any of the new jigsaw vm options is specified. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib .. + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @compile ../test-classes/Hello.java + * @run main CheckUnsupportedDumpingOptions + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class CheckUnsupportedDumpingOptions { + private static final String[] jigsawOptions = { + "-m", + "--limit-modules", + "--module-path", + "--upgrade-module-path", + "--patch-module" + }; + private static final String[] optionValues = { + "mymod", + "mymod", + "mydir", + ".", + "java.naming=javax.naming.spi.NamingManger" + }; + private static final int infoIdx = 1; + + public static void main(String[] args) throws Exception { + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"), + "mods/java.naming"); + + JarBuilder.build("hello", "Hello"); + String appJar = TestCommon.getTestJar("hello.jar"); + String appClasses[] = {"Hello"}; + for (int i = 0; i < jigsawOptions.length; i++) { + OutputAnalyzer output; + if (i == 5) { + // --patch-module + output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables", + jigsawOptions[i] + optionValues[i] + appJar); + } else { + output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables", + jigsawOptions[i], optionValues[i]); + } + if (i < infoIdx) { + output.shouldContain("Cannot use the following option " + + "when dumping the shared archive: " + jigsawOptions[i]) + .shouldHaveExitValue(1); + } else { + output.shouldContain("Info: the " + jigsawOptions[i] + + " option is ignored when dumping the shared archive"); + if (optionValues[i].equals("mymod")) { + // java will throw FindException for a module + // which cannot be found during init_phase2() of vm init + output.shouldHaveExitValue(1) + .shouldContain("java.lang.module.FindException: Module mymod not found"); + } else { + output.shouldHaveExitValue(0); + } + } + } + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java new file mode 100644 index 00000000000..2513d0e5a19 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2015, 2017, 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 Test combinations of jigsaw options that affect the use of AppCDS + * + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib .. + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @compile ../test-classes/Hello.java ../test-classes/HelloMore.java + * @run main JigsawOptionsCombo + */ +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; +import java.util.ArrayList; + + +// Remaining WORK: TODO: +// 1. test with -m initial-module; waiting for changes from Chris will provide +// utils to build modules +// 2. Loading classes from Jmod files - waiting on utils +// 3. Loading classes from exploded module dir" + +public class JigsawOptionsCombo { + + public static void main(String[] args) throws Exception { + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"), + "mods/java.naming"); + + JarBuilder.build("hello", "Hello"); + JarBuilder.build("hello_more", "HelloMore"); + + (new JigsawOptionsCombo()).runTests(); + } + + + private ArrayList testCaseTable = new ArrayList(); + + public static String infoDuringDump(String option) { + return "Info: the " + option + + " option is ignored when dumping the shared archive"; + } + + public void runTests() throws Exception { + + testCaseTable.add(new TestCase( + "basic: Basic dump and execute, to verify the test plumbing works", + "", "", 0, + "", "", 0) ); + + String bcpArg = "-Xbootclasspath/a:" + + TestCommon.getTestJar("hello_more.jar"); + + testCaseTable.add(new TestCase( + "Xbootclasspath/a: is OK for both dump and run time", + bcpArg, "", 0, + bcpArg, "", 0) ); + + testCaseTable.add(new TestCase( + "module-path-01: --module-path is ignored for dump time", + "--module-path mods", + infoDuringDump("--module-path"), 0, + null, null, 0) ); + + testCaseTable.add(new TestCase( + "module-path-02: --module-path is ok for run time", + "", "", 0, + "--module-path mods", "", 0) ); + + testCaseTable.add(new TestCase( + "add-modules-01: --add-modules is ok at dump time", + "--add-modules java.management", + "", 0, + null, null, 0) ); + + testCaseTable.add(new TestCase( + "add-modules-02: --add-modules is ok at run time", + "", "", 0, + "--add-modules java.management", "", 0) ); + + testCaseTable.add(new TestCase( + "limit-modules-01: --limit-modules is ignored at dump time", + "--limit-modules java.base", + infoDuringDump("--limit-modules"), 0, + null, null, 0) ); + + testCaseTable.add(new TestCase( + "limit-modules-02: --limit-modules is ok at run time", + "", "", 0, + "--limit-modules java.base", "", 0) ); + + testCaseTable.add(new TestCase( + "upgrade-module-path-01: --upgrade-module-path is ignored at dump time", + "--upgrade-module-path mods", + infoDuringDump("--upgrade-module-path"), 0, + null, null, 0) ); + + testCaseTable.add(new TestCase( + "-upgrade-module-path-module-path-02: --upgrade-module-path is ok at run time", + "", "", 0, + "--upgrade-module-path mods", "", 0) ); + + for (TestCase tc : testCaseTable) tc.execute(); + } + + + // class representing a singe test case + public class TestCase { + String description; + String dumpTimeArgs; + String dumpTimeExpectedOutput; + int dumpTimeExpectedExitValue; + String runTimeArgs; + String runTimeExpectedOutput; + int runTimeExpectedExitValue; + + private String appJar = TestCommon.getTestJar("hello.jar"); + private String appClasses[] = {"Hello"}; + + + public TestCase(String description, + String dumpTimeArgs, String dumpTimeExpectedOutput, int dumpTimeExpectedExitValue, + String runTimeArgs, String runTimeExpectedOutput, int runTimeExpectedExitValue) { + + this.description = description; + this.dumpTimeArgs = dumpTimeArgs; + this.dumpTimeExpectedOutput = dumpTimeExpectedOutput; + this.dumpTimeExpectedExitValue = dumpTimeExpectedExitValue; + this.runTimeArgs = runTimeArgs; + this.runTimeExpectedOutput = runTimeExpectedOutput; + this.runTimeExpectedExitValue = runTimeExpectedExitValue; + } + + + public void execute() throws Exception { + System.out.println("Description: " + description); + + // ===== dump step - create the archive + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, appClasses, getDumpOptions()); + + if (dumpTimeExpectedExitValue == 0) { + TestCommon.checkDump(dumpOutput, dumpTimeExpectedOutput); + } else { + dumpOutput.shouldMatch(dumpTimeExpectedOutput); + dumpOutput.shouldHaveExitValue(dumpTimeExpectedExitValue); + } + + // ===== exec step - use the archive + if (runTimeArgs != null) { + OutputAnalyzer execOutput = TestCommon.exec(appJar, getRunOptions()); + + if (runTimeExpectedExitValue == 0) { + TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World"); + } else { + execOutput.shouldMatch(dumpTimeExpectedOutput); + execOutput.shouldHaveExitValue(dumpTimeExpectedExitValue); + } + } + } + + + // dump command line options can be separated by a space + private String[] getDumpOptions() { + return dumpTimeArgs.split(" "); + } + + + // run command line options can be separated by a space + private String[] getRunOptions() { + ArrayList result = new ArrayList<>(); + + if (runTimeArgs != "") { + String splitArgs[] = runTimeArgs.split(" "); + for (String arg : splitArgs) + result.add(arg); + } + + result.add("Hello"); + return result.toArray(new String[1]); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java new file mode 100644 index 00000000000..07a09fda627 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary a test to demonstrate that an application class in the -cp + * will be archived although --patch-module is specified. The class in + * the -cp has no dependencies on the class in the --patch-module. + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main AppClassInCP + */ + +import java.io.File; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class AppClassInCP { + private static String moduleJar; + private static String appJar; + + public static void main(String args[]) throws Throwable { + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming.jar file. + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + String classDir = System.getProperty("test.classes"); + + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"), + classDir); + + // Build the jar file that will be used for the module "java.naming". + JarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); + moduleJar = TestCommon.getTestJar("javanaming.jar"); + + String source2 = "package mypackage; " + + "public class Hello { " + + " static { " + + " System.out.println(\"Hello!\"); " + + " } " + + "}"; + ClassFileInstaller.writeClassToDisk("mypackage/Hello", + InMemoryJavaCompiler.compile("mypackage.Hello", source2), + classDir); + + JarBuilder.build("hello", "mypackage/Hello"); + appJar = TestCommon.getTestJar("hello.jar"); + + System.out.println("Test dumping with --patch-module"); + OutputAnalyzer output = + TestCommon.dump(appJar, + TestCommon.list("javax/naming/spi/NamingManager", "mypackage/Hello"), + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello"); + TestCommon.checkDump(output, "Loading classes to share"); + + String classPath = appJar + File.pathSeparator + classDir; + System.out.println("classPath: " + classPath); + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "-cp", classPath, + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello"); + TestCommon.checkExec(output, + "I pass!", + "Hello!", + "Hello source: shared objects file"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java new file mode 100644 index 00000000000..9f6fbbb2ad1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary if a class is defined to a package which is not defined to any + * module in the jimage, the class will not be found during dump + * time but it will be used during run time. + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main CustomPackage + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class CustomPackage { + private static String moduleJar; + + public static void main(String args[]) throws Throwable { + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming.jar file. + String source = "package javax.naming.myspi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("javax/naming/myspi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.myspi.NamingManager", source, "--patch-module=java.naming"), + System.getProperty("test.classes")); + + // Build the jar file that will be used for the module "java.naming". + JarBuilder.build("javanaming", "javax/naming/myspi/NamingManager"); + moduleJar = TestCommon.getTestJar("javanaming.jar"); + + System.out.println("Test dumping with --patch-module"); + OutputAnalyzer output = + TestCommon.dump(null, + TestCommon.list("javax/naming/myspi/NamingManager"), + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.myspi.NamingManager"); + TestCommon.checkDump(output, "Preload Warning: Cannot find javax/naming/myspi/NamingManager"); + + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.myspi.NamingManager"); + TestCommon.checkExec(output, "I pass!"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java new file mode 100644 index 00000000000..b614f58a551 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary different settings of --patch-module at dump time and runtime are + * acceptable. The class found in runtime --patch-module entry should + * be used. + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main MismatchedPatchModule + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class MismatchedPatchModule { + private static String moduleJar; + + public static void main(String args[]) throws Throwable { + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming.jar file. + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"), + System.getProperty("test.classes")); + + // Build the jar file that will be used for the module "java.naming". + JarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); + moduleJar = TestCommon.getTestJar("javanaming.jar"); + + // Case 1: --patch-module specified for dump time and run time + System.out.println("Case 1: --patch-module specified for dump time and run time"); + OutputAnalyzer output = + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager"), + "--patch-module=java.naming=" + moduleJar, + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkDump(output, "Loading classes to share"); + + // javax.naming.spi.NamingManager is not patched at runtime + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.naming2=" + moduleJar, + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + output.shouldNotContain("I pass!"); + + // Case 2: --patch-module specified for dump time but not for run time + System.out.println("Case 2: --patch-module specified for dump time but not for run time"); + output = + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager"), + "--patch-module=java.naming=" + moduleJar, + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkDump(output, "Loading classes to share"); + + // javax.naming.spi.NamingManager is not patched at runtime + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + output.shouldNotContain("I pass!"); + + // Case 3: --patch-module specified for run time but not for dump time + System.out.println("Case 3: --patch-module specified for run time but not for dump time"); + output = + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager"), + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkDump(output, "Loading classes to share"); + + // javax.naming.spi.NamingManager is patched at runtime + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkExec(output, "I pass!"); + + // Case 4: mismatched --patch-module entry counts between dump time and run time + System.out.println("Case 4: mismatched --patch-module entry counts between dump time and run time"); + output = + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager"), + "--patch-module=java.naming=" + moduleJar, + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkDump(output, "Loading classes to share"); + + // javax.naming.spi.NamingManager is patched at runtime + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.naming=" + moduleJar, + "--patch-module=java.naming2=" + moduleJar, + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkExec(output, "I pass!"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java new file mode 100644 index 00000000000..854d4419922 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary a simple test to ensure that a directory in the --patch-module + * option does not affect dump process + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main PatchDir + */ + +import java.io.File; +import jdk.test.lib.compiler.InMemoryJavaCompiler; + +public class PatchDir { + private static String moduleJar; + + public static void main(String args[]) throws Throwable { + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming.jar file. + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + String classDir = System.getProperty("test.classes"); + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"), + classDir); + + JarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); + moduleJar = TestCommon.getTestJar("javanaming.jar"); + + System.out.println("Test dumping with --patch-module"); + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager"), + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "PatchMain", "javax.naming.spi.NamingManager") + .shouldContain("Loading classes to share") + .shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java new file mode 100644 index 00000000000..726cf1b7675 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary sharing is disabled if java.base is patch at runtime + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main PatchJavaBase + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class PatchJavaBase { + private static String moduleJar; + + public static void main(String args[]) throws Throwable { + + String source = "package java.lang; " + + "public class NewClass { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("java/lang/NewClass", + InMemoryJavaCompiler.compile("java.lang.NewClass", source, "--patch-module=java.base"), + System.getProperty("test.classes")); + + JarBuilder.build("javabase", "java/lang/NewClass"); + moduleJar = TestCommon.getTestJar("javabase.jar"); + + System.out.println("Test dumping with --patch-module"); + OutputAnalyzer output = + TestCommon.dump(null, null, + "--patch-module=java.base=" + moduleJar, + "PatchMain", "java.lang.NewClass"); + TestCommon.checkDump(output, "Loading classes to share"); + + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.base=" + moduleJar, + "PatchMain", "java.lang.NewClass"); + output.shouldContain("CDS is disabled when java.base module is patched"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchMain.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchMain.java new file mode 100644 index 00000000000..86430957875 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchMain.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, 2017, 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. + * + */ + +// This loads the class affected by the --patch-module option. For the test to pass +// it must load the class from the --patch-module directory, not the jimage file. +public class PatchMain { + public static void main(String[] args) throws Exception { + for (int i = 0; i < args.length; i++) { + Class.forName(args[i]); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java new file mode 100644 index 00000000000..80959541cfd --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary a simple test to ensure that class is loaded from jar file in --patch-module at runtime + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main Simple + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class Simple { + private static String moduleJar; + + public static void main(String args[]) throws Throwable { + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming.jar file. + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"), + System.getProperty("test.classes")); + + // Build the jar file that will be used for the module "java.naming". + JarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); + moduleJar = TestCommon.getTestJar("javanaming.jar"); + + System.out.println("Test dumping with --patch-module"); + OutputAnalyzer output = + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager"), + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkDump(output, "Loading classes to share"); + + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkExec(output, "I pass!"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java new file mode 100644 index 00000000000..de460b5f2ee --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary the class in the -cp is a subclass of the class in --patch-module. The + * patched class should be used at runtime. + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main SubClassOfPatchedClass + */ + +import java.io.File; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class SubClassOfPatchedClass { + private static String moduleJar; + private static String appJar; + + public static void main(String args[]) throws Throwable { + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming.jar file. + String source = "package javax.naming; " + + "public class Reference { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + String classDir = System.getProperty("test.classes"); + + ClassFileInstaller.writeClassToDisk("javax/naming/Reference", + InMemoryJavaCompiler.compile("javax.naming.Reference", source, "--patch-module=java.naming"), + classDir); + + // Build the jar file that will be used for the module "java.naming". + JarBuilder.build("javanaming", "javax/naming/Reference"); + moduleJar = TestCommon.getTestJar("javanaming.jar"); + + String source2 = "package mypackage; " + + "public class MyReference extends javax.naming.Reference { " + + " static { " + + " System.out.println(\"MyReference!\"); " + + " } " + + " public MyReference(String mystring) { " + + " super(mystring); " + + " } " + + "}"; + ClassFileInstaller.writeClassToDisk("mypackage/MyReference", + InMemoryJavaCompiler.compile("mypackage.MyReference", source2), + classDir); + + JarBuilder.build("myjavanaming", "mypackage/MyReference"); + appJar = TestCommon.getTestJar("myjavanaming.jar"); + + System.out.println("Test dumping with --patch-module"); + OutputAnalyzer output = + TestCommon.dump(appJar, + TestCommon.list("javax/naming/Reference", "mypackage/MyReference"), + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "PatchMain", "javax.naming.Reference", "mypackage.MyReference"); + TestCommon.checkDump(output, "Loading classes to share"); + + String classPath = appJar + File.pathSeparator + classDir; + System.out.println("classPath: " + classPath); + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "-cp", classPath, + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "PatchMain", "javax.naming.Reference", "mypackage.MyReference"); + TestCommon.checkExec(output, + "I pass!", + "MyReference source: file:"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java new file mode 100644 index 00000000000..ef8b71a2165 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @summary a patched class found in --patch-module should be used at runtime + * @library ../.. + * @library /test/hotspot/jtreg/testlibrary + * @library /test/lib + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchMain + * @run main TwoJars + */ + +import java.io.File; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; + +public class TwoJars { + private static String moduleJar; + private static String moduleJar2; + + public static void main(String args[]) throws Throwable { + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming.jar file. + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + // Create a class file in the module java.naming. This class file + // will be put in the javanaming2.jar file. + String source2 = "package javax.naming.spi; " + + "public class DirectoryManager { " + + " static { " + + " System.out.println(\"I fail!\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"), + System.getProperty("test.classes")); + + // Build the jar file that will be used for the module "java.naming". + JarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); + moduleJar = TestCommon.getTestJar("javanaming.jar"); + + ClassFileInstaller.writeClassToDisk("javax/naming/spi/DirectoryManager", + InMemoryJavaCompiler.compile("javax.naming.spi.DirectoryManager", source2, "--patch-module=java.naming"), + System.getProperty("test.classes")); + + // Build the jar file that will be used for the module "java.naming". + JarBuilder.build("javanaming2", "javax/naming/spi/DirectoryManager"); + moduleJar2 = TestCommon.getTestJar("javanaming2.jar"); + + System.out.println("Test dumping with --patch-module"); + OutputAnalyzer output = + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager"), + "--patch-module=java.naming=" + moduleJar2 + File.pathSeparator + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkDump(output, "Loading classes to share"); + + output = TestCommon.execCommon( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.naming=" + moduleJar2 + File.pathSeparator + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager"); + TestCommon.checkExec(output, "I pass"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java new file mode 100644 index 00000000000..71392801fda --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2015, 2017, 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 AppCDS tests for testing -Xbootclasspath/a + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @compile src/jdk/test/Main.java + * @compile src/com/sun/tools/javac/Main2.jasm + * @compile src/sun/nio/cs/ext/MyClass.java + * @compile src/sun/nio/cs/ext1/MyClass.java + * @run main BootAppendTests + */ + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class BootAppendTests { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path CLASSES_DIR = Paths.get("classes"); + + private static final String MAIN_CLASS = "jdk.test.Main"; + private static final String APP_MODULE_CLASS = "com/sun/tools/javac/Main2"; + private static final String BOOT_APPEND_MODULE_CLASS = "sun/nio/cs/ext/MyClass"; + private static final String BOOT_APPEND_CLASS = "sun/nio/cs/ext1/MyClass"; + private static final String[] ARCHIVE_CLASSES = + {APP_MODULE_CLASS, BOOT_APPEND_MODULE_CLASS, BOOT_APPEND_CLASS}; + + private static String appJar; + private static String bootAppendJar; + private static String testArchiveName; + + public static void main(String... args) throws Exception { + dumpArchive(); + + System.out.println("TESTCASE: 1: testBootAppendModuleClassWithoutAppCDS"); + testBootAppendModuleClassWithoutAppCDS(); + + System.out.println("TESTCASE: 2" ); + testBootAppendModuleClassWithAppCDS(); + + System.out.println("TESTCASE: 3" ); + testBootAppendExcludedModuleClassWithoutAppCDS(); + + System.out.println("TESTCASE: 4" ); + testBootAppendExcludedModuleClassWithAppCDS(); + + System.out.println("TESTCASE: 5" ); + testBootAppendClassWithoutAppCDS(); + + System.out.println("TESTCASE: 6" ); + testBootAppendClassWithAppCDS(); + + System.out.println("TESTCASE: 7" ); + testBootAppendAppModuleClassWithoutAppCDS(); + + System.out.println("TESTCASE: 9" ); + testBootAppendAppModuleClassWithAppCDS(); + + System.out.println("TESTCASE: 9" ); + testBootAppendAppExcludeModuleClassWithoutAppCDS(); + + System.out.println("TESTCASE: 10" ); + testBootAppendAppExcludeModuleClassAppCDS(); + } + + static void dumpArchive() throws Exception { + JarBuilder.build("classpathtests", "jdk/test/Main"); + appJar = TestCommon.getTestJar("classpathtests.jar"); + + JarBuilder.build("bootAppend", + APP_MODULE_CLASS, BOOT_APPEND_MODULE_CLASS, BOOT_APPEND_CLASS); + bootAppendJar = TestCommon.getTestJar("bootAppend.jar"); + + OutputAnalyzer output1 = TestCommon.dump( + appJar, TestCommon.list(ARCHIVE_CLASSES), "-Xbootclasspath/a:" + bootAppendJar); + TestCommon.checkDump(output1); + + if (!TestCommon.isUnableToMap(output1)) { + // Make sure all the classes were successfully archived. + for (String archiveClass : ARCHIVE_CLASSES) { + output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass); + } + } + + testArchiveName = TestCommon.getCurrentArchiveName(); + } + + // Test #1: A class in package defined in boot module + // - should not be loaded from the -Xbootclasspath/a without AppCDS + public static void testBootAppendModuleClassWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar) + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #1", BOOT_APPEND_MODULE_CLASS, "false"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + // Test #2: A shared class in package defined in boot module that's archived + // from -Xbootclasspath/a + // - should not be loaded by AppCDS + public static void testBootAppendModuleClassWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "-Xbootclasspath/a:" + bootAppendJar, + MAIN_CLASS, + "Test #2", BOOT_APPEND_MODULE_CLASS, "false"); + TestCommon.checkExec(output); + } + + + // Test #3: A class in excluded package defined in boot module + // - should be loaded from the -Xbootclasspath/a by the boot classloader + public static void testBootAppendExcludedModuleClassWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar, + "--limit-modules", "java.base") + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #3", BOOT_APPEND_MODULE_CLASS, "true", "BOOT"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + // Test #4: A shared class in excluded package that's archived from + // -Xbootclasspath/a + // - should be loaded from the archive by the bootstrap classloader + public static void testBootAppendExcludedModuleClassWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "-Xbootclasspath/a:" + bootAppendJar, + "--limit-modules", "java.base", + "-XX:+TraceClassLoading", + MAIN_CLASS, + "Test #4", BOOT_APPEND_MODULE_CLASS, "true", "BOOT"); + TestCommon.checkExec(output); + if (!TestCommon.isUnableToMap(output)) + output.shouldContain("[class,load] sun.nio.cs.ext.MyClass source: shared objects file"); + } + + + // Test #5: A class not in package defined in boot module + // - should be loaded from the -Xbootclasspath/a without AppCDS + public static void testBootAppendClassWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar) + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #5", BOOT_APPEND_CLASS, "true", "BOOT"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + + // Test #6: A shared class not in package defined in boot module that's + // archived from -Xbootclasspath/a + // - should be loaded from the archive by the bootstrap class loader + public static void testBootAppendClassWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "-Xbootclasspath/a:" + bootAppendJar, + "-XX:+TraceClassLoading", + MAIN_CLASS, + "Test #6", BOOT_APPEND_CLASS, "true", "BOOT"); + TestCommon.checkExec(output); + if (!TestCommon.isUnableToMap(output)) + output.shouldContain("[class,load] sun.nio.cs.ext1.MyClass source: shared objects file"); + } + + + // Test #7: A class in package defined in jimage app module + // - should not be loaded from the -Xbootclasspath/a without AppCDS + public static void testBootAppendAppModuleClassWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar) + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #7", APP_MODULE_CLASS, "false"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + + // Test #8: A shared class in package defined in jimage app module that's + // archived from -Xbootclasspath/a + // - should not be loaded from the archive + public static void testBootAppendAppModuleClassWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "-Xbootclasspath/a:" + bootAppendJar, + MAIN_CLASS, + "Test #8", APP_MODULE_CLASS, "false"); + TestCommon.checkExec(output); + } + + + // Test #9: A class in excluded package defined in jimage app module + // - should be loaded from the -Xbootclasspath/a without AppCDS + public static void testBootAppendAppExcludeModuleClassWithoutAppCDS() + throws Exception { + + CDSOptions opts = (new CDSOptions()) + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar, + "--limit-modules", "java.base") + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + // Test #10: A shared class in excluded package defined in jimage app module + // - should be loaded from the -Xbootclasspath/a with AppCDS + public static void testBootAppendAppExcludeModuleClassAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "-Xbootclasspath/a:" + bootAppendJar, + "-XX:+TraceClassLoading", + "--limit-modules", "java.base", + MAIN_CLASS, + "Test #10", APP_MODULE_CLASS, "true", "BOOT"); + TestCommon.checkExec(output); + + if (!TestCommon.isUnableToMap(output)) + output.shouldContain("[class,load] com.sun.tools.javac.Main2 source: shared objects file"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/ClassPathTests.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/ClassPathTests.java new file mode 100644 index 00000000000..6f929ab227f --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/ClassPathTests.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library ../.. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules jdk.jartool/sun.tools.jar + * @compile src/jdk/test/Main.java + * @compile src/com/sun/tools/javac/Main.jasm + * @compile src/com/sun/tools/javac/Main2.jasm + * @compile src/javax/activation/UnsupportedDataTypeException2.jasm + * @run main ClassPathTests + * @summary AppCDS tests for testing classpath/package conflicts + */ + +/* + * These tests will verify that AppCDS will correctly handle archived classes + * on the classpath that are in a package that is also exported by the jimage. + * These classes should fail to load unless --limit-modules is used to hide the + * package exported by the jimage. There are 8 variants of this test: + * - With a jimage app package and with a jimage ext package + * - With --limit-modules and without --limit-modules + * - With AppCDS and without AppCDS (to verify behaviour is the same for both). + * + * There is also a 9th test to verify that when --limit-modules is used, a jimage + * class in the archive can be replaced by a classpath class with the + * same name and package. + */ + +import java.lang.reflect.Method; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.Asserts; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + + +public class ClassPathTests { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path CLASSES_DIR = Paths.get("classes"); + + // the test module + private static final String MAIN_CLASS = "jdk.test.Main"; + private static final String LIMITMODS_MAIN_CLASS = "jdk.test.LimitModsMain"; + + // test classes to archive. These are both in UPGRADED_MODULES + private static final String JIMAGE_CLASS = "com/sun/tools/javac/Main"; + private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/Main2"; + private static final String PLATFORM_ARCHIVE_CLASS = "javax/activation/UnsupportedDataTypeException2"; + private static final String[] ARCHIVE_CLASSES = {APP_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, JIMAGE_CLASS}; + private static final int NUMBER_OF_TEST_CASES = 10; + + private static String appJar; + private static String testArchiveName; + + + public static void main(String[] args) throws Exception { + ClassPathTests tests = new ClassPathTests(); + tests.dumpArchive(); + + Method[] methods = tests.getClass().getDeclaredMethods(); + int numOfTestMethodsRun = 0; + for (Method m : methods) { + if (m.getName().startsWith("test")) { + System.out.println("About to run test method: " + m.getName()); + m.invoke(tests); + numOfTestMethodsRun++; + } + } + + Asserts.assertTrue((numOfTestMethodsRun == NUMBER_OF_TEST_CASES), + "Expected " + NUMBER_OF_TEST_CASES + " test methods to run, actual number is " + + numOfTestMethodsRun); + } + + private void dumpArchive() throws Exception { + // Create a jar file with all the classes related to this test. + JarBuilder.build( "classpathtests", + APP_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, JIMAGE_CLASS, + "jdk/test/Main"); + appJar = TestCommon.getTestJar("classpathtests.jar"); + + // dump the archive with altnernate jdk.comiler and jdk.activation classes in the class list + OutputAnalyzer output1 = TestCommon.dump(appJar, TestCommon.list(ARCHIVE_CLASSES)); + TestCommon.checkDump(output1); + // Only a class that belongs to a module which is not defined by default + // can be found. In this case the PLATFORM_ARCHIVE_CLASS belongs + // to the java.activation which is not defined by default; it is the only + // class can be found during dumping. + for (String archiveClass : ARCHIVE_CLASSES) { + if (archiveClass.equals(PLATFORM_ARCHIVE_CLASS)) { + output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass); + } else { + output1.shouldContain("Preload Warning: Cannot find " + archiveClass); + } + } + + testArchiveName = TestCommon.getCurrentArchiveName(); + } + + // #1: Archived classpath class in same package as jimage app class. With AppCDS. + // Should fail to load. + public void testAppClassWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, MAIN_CLASS, + "Test #1", APP_ARCHIVE_CLASS, "false"); // last 3 args passed to test + TestCommon.checkExec(output); + } + + // #2: Archived classpath class in same package as jimage app class. Without AppCDS. + // Should fail to load. + public void testAppClassWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-cp", appJar) + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #2", APP_ARCHIVE_CLASS, "false"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + // For tests #3 and #4, we need to "--add-modules java.activation" since the + // java.activation module won't be defined by default. + + // #3: Archived classpath class in same package as jimage ext class. With AppCDS. + // Should fail to load. + public void testExtClassWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, "--add-modules", "java.activation", MAIN_CLASS, + "Test #3", PLATFORM_ARCHIVE_CLASS, "false"); // last 3 args passed to test + TestCommon.checkExec(output); + } + + // #4: Archived classpath class in same package as jimage ext class. Without AppCDS. + // Should fail to load. + public void testExtClassWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-cp", appJar, "--add-modules", "java.activation") + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #4", PLATFORM_ARCHIVE_CLASS, "false"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + // #5: Archived classpath class in same package as jimage app class. With AppCDS. + // Should load because --limit-modules is used. + public void testAppClassWithLimitModsWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "--limit-modules", "java.base", + MAIN_CLASS, + "Test #5", APP_ARCHIVE_CLASS, "true"); // last 3 args passed to test + TestCommon.checkExec(output); + } + + // #6: Archived classpath class in same package as jimage app class. Without AppCDS. + // Should load because --limit-modules is used. + public void testAppClassWithLimitModsWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-cp", appJar, "--limit-modules", "java.base") + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #6", APP_ARCHIVE_CLASS, "true"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + // #7: Archived classpath class in same package as jimage ext class. With AppCDS. + // Should load because --limit-modules is used. + public void testExtClassWithLimitModsWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "--limit-modules", "java.base", + MAIN_CLASS, + "Test #7", PLATFORM_ARCHIVE_CLASS, "true"); // last 3 args passed to test + TestCommon.checkExec(output); + } + + // #8: Archived classpath class in same package as jimage ext class. Without AppCDS. + // Should load because --limit-modules is used. + public void testExtClassWithLimitModsWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-cp", appJar, "--limit-modules", "java.base") + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #8", PLATFORM_ARCHIVE_CLASS, "true"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + + // #9: Archived classpath class with same name as jimage app class. With AppCDS. + // Should load because --limit-modules is used. + public void testReplacingJImageClassWithAppCDS() throws Exception { + OutputAnalyzer output = TestCommon.exec( + appJar, + "--limit-modules", "java.base", "-XX:+TraceClassLoading", + MAIN_CLASS, + "Test #9", JIMAGE_CLASS, "true"); // last 3 args passed to test + TestCommon.checkExec(output); + } + + // #10: Archived classpath class with same name as jimage app class. Without AppCDS. + // Should load because --limit-modules is used. Note the archive will actually contain + // the original jimage version of the class, but AppCDS should refuse to load it + // since --limit-modules is used. This should result in the -cp version being used. + public void testReplacingJImageClassWithoutAppCDS() throws Exception { + CDSOptions opts = (new CDSOptions()) + .addPrefix("-cp", appJar, "--limit-modules", "java.base") + .setArchiveName(testArchiveName) + .addSuffix(MAIN_CLASS, "Test #10", JIMAGE_CLASS, "true"); + + CDSTestUtils.runWithArchiveAndCheck(opts); + } + +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java new file mode 100644 index 00000000000..05311e818a1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, 2017, 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 Ensure that classes found in jimage takes precedence over classes found in -Xbootclasspath/a. + * AppCDS does not support uncompressed oops + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.activation + * jdk.jartool/sun.tools.jar + * @compile ../../test-classes/DummyClassHelper.java + * @compile ../../test-classes/java/net/HttpCookie.jasm + * @compile ../../test-classes/javax/activation/MimeType.jasm + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main DummyClassesInBootClassPath + */ + +import java.io.File; +import java.util.List; +import java.util.ArrayList; +import jdk.test.lib.process.OutputAnalyzer; + +public class DummyClassesInBootClassPath { + private static final String METHOD_NAME = "thisClassIsDummy()"; + + public static void main(String[] args) throws Exception { + String classNames[] = { "java/net/HttpCookie", + "javax/activation/MimeType"}; + JarBuilder.build("dummyClasses", classNames[0], classNames[1]); + + String appJar = TestCommon.getTestJar("dummyClasses.jar"); + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, classNames, "-Xbootclasspath/a:" + appJar); + + List argsList = new ArrayList(); + for (int i = 0; i < classNames.length; i++) { + argsList.add(classNames[i].replace('/', '.')); + } + String[] arguments = new String[argsList.size()]; + arguments = argsList.toArray(arguments); + OutputAnalyzer execOutput = TestCommon.execCommon( + "-cp", TestCommon.getTestDir("."), "-verbose:class", + "--add-modules", "java.activation", + "-Xbootclasspath/a:" + appJar, "DummyClassHelper", + arguments[0], arguments[1]); + for (int i = 0; i < arguments.length; i++) { + TestCommon.checkExec(execOutput, + "java.lang.NoSuchMethodException: " + arguments[i] + "." + + METHOD_NAME); + } + + JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + String whiteBoxJar = TestCommon.getTestJar("WhiteBox.jar"); + String bootClassPath = "-Xbootclasspath/a:" + appJar + + File.pathSeparator + whiteBoxJar; + argsList.add("testWithWhiteBox"); + arguments = new String[argsList.size()]; + arguments = argsList.toArray(arguments); + String[] opts = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + bootClassPath, "-XX:+TraceClassPaths", "DummyClassHelper", + arguments[0], arguments[1], arguments[2]}; + OutputAnalyzer output = TestCommon.execCommon(opts); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java new file mode 100644 index 00000000000..a635603473e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015, 2017, 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 Test a few scenarios if an empty class, which has the same name as the one in the jimage, is specified in the -Xbootclasspath/a + * 1) boot loader will always load the class from the bootclasspath + * 2) app loader will load the class from the jimage by default; + * app loader will load the class from the bootclasspath if the + * "--limit-modules java.base" option is specified + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @compile ../../test-classes/EmptyClassHelper.java + * @compile ../../test-classes/com/sun/tools/javac/Main.jasm + * @run main EmptyClassInBootClassPath + */ + +import java.io.File; +import java.lang.*; +import java.lang.reflect.*; +import java.util.List; +import java.util.ArrayList; +import jdk.test.lib.process.OutputAnalyzer; + +public class EmptyClassInBootClassPath { + static final String EXPECTED_EXCEPTION = + "java.lang.NoSuchMethodException: com.sun.tools.javac.Main.main([Ljava.lang.String;)"; + public static void main(String[] args) throws Exception { + String[] className = {"com/sun/tools/javac/Main"}; + JarBuilder.build("emptyClass", className); + String appJar = TestCommon.getTestJar("emptyClass.jar"); + JarBuilder.build("EmptyClassHelper", "EmptyClassHelper"); + String helperJar = TestCommon.getTestJar("EmptyClassHelper.jar"); + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, className, "-Xbootclasspath/a:" + appJar); + TestCommon.checkDump(dumpOutput); + dumpOutput.shouldNotContain("Preload Warning: skipping class from -Xbootclasspath/a " + className[0]); + + String bootclasspath = "-Xbootclasspath/a:" + appJar; + String classPath = "-Djava.class.path=" + appJar + File.pathSeparator + helperJar; + List argsList = new ArrayList(); + argsList.add(classPath); + argsList.add(bootclasspath); + argsList.add("--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED"); + argsList.add("EmptyClassHelper"); + + // case 1: load class in bootclasspath using app loader + argsList.add("useAppLoader"); + String[] opts = new String[argsList.size()]; + opts = argsList.toArray(opts); + OutputAnalyzer runOutput = TestCommon.execCommon(opts); + TestCommon.checkExec(runOutput, "appLoader found method main"); + + // case 2: load class in bootclasspath using boot loader + argsList.remove(argsList.size() - 1); + argsList.add("useBootLoader"); + opts = new String[argsList.size()]; + opts = argsList.toArray(opts); + runOutput = TestCommon.execCommon(opts); + TestCommon.checkExec(runOutput, EXPECTED_EXCEPTION); + + // case 3: load class in bootclasspath using app loader with '--limit-modules java.base' + argsList.add(0, "--limit-modules"); + argsList.add(1, "java.base"); + argsList.remove(argsList.size() - 1); + argsList.add("useAppLoader"); + opts = new String[argsList.size()]; + opts = argsList.toArray(opts); + runOutput = TestCommon.execCommon(opts); + TestCommon.checkExec(runOutput, EXPECTED_EXCEPTION); + + // case 4: load class in bootclasspath using boot loader with '--limit-modules java.base' + argsList.remove(argsList.size() - 1); + argsList.add("useBootLoader"); + opts = new String[argsList.size()]; + opts = argsList.toArray(opts); + runOutput = TestCommon.execCommon(opts); + TestCommon.checkExec(runOutput, EXPECTED_EXCEPTION); + + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main.jasm b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main.jasm new file mode 100644 index 00000000000..efe6c4a8e6e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main.jasm @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 2017, 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 com/sun/tools/javac; + +public class Main + version 51:0 +{ + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public Method toString:"()Ljava/lang/String;" + stack 1 locals 1 +{ + ldc String "hi"; + areturn; +} + +} // end class Main diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main2.jasm b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main2.jasm new file mode 100644 index 00000000000..3d0f43256bf --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main2.jasm @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 2017, 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 com/sun/tools/javac; + +public class Main2 + version 51:0 +{ + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public Method toString:"()Ljava/lang/String;" + stack 1 locals 1 +{ + ldc String "hi"; + areturn; +} + +} // end class Main2 diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/javax/activation/UnsupportedDataTypeException2.jasm b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/javax/activation/UnsupportedDataTypeException2.jasm new file mode 100644 index 00000000000..3a30e511397 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/javax/activation/UnsupportedDataTypeException2.jasm @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 2017, 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 javax/activation; + +public class UnsupportedDataTypeException2 + version 51:0 +{ + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public Method toString:"()Ljava/lang/String;" + stack 1 locals 1 +{ + ldc String "hi"; + areturn; +} + +} // end class UnsupportedDataTypeException2 diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/jdk/test/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/jdk/test/Main.java new file mode 100644 index 00000000000..752fd9b7baf --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/jdk/test/Main.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +/** + * Tests loading an archived class that has the same class name as one in the + * jimage. The class should normally fail to load since a classpath class is not + * allowed to have the same package name as a module in the jimage. However, + * if --limit-modules was used then archived class should be loaded. + */ + +package jdk.test; + +public class Main { + static final ClassLoader BOOT_LOADER = null; + static final ClassLoader PLATFORM_LOADER = ClassLoader.getPlatformClassLoader(); + static final ClassLoader SYS_LOADER = ClassLoader.getSystemClassLoader(); + + public static void main(String[] args) throws Exception { + boolean shouldLoad = false; + ClassLoader expectedLoader = SYS_LOADER; + + /* + * 3 Arguments are passed to this test: + * 1. testName: Name of the test being run. + * 2. className: Name of the class to load and instantiate. + * 3. shouldLoad: Either "true" or "false" to indicate whether the class should + * successfully load ("true" indicates --limit-modules was used.) + * The 4th argument is optional. It specifies the classloader. + */ + + assertTrue(args.length <= 4); + String testName = args[0]; + String className = args[1].replace('/', '.'); + String shouldLoadName = args[2]; // "true" or "false" + String loaderName = "SYS"; + if (args.length == 4) { + loaderName = args[3]; + } + + if (shouldLoadName.equals("true")) { + shouldLoad = true; + } else if (shouldLoadName.equals("false")) { + shouldLoad = false; + } else { + assertTrue(false); + } + + if (loaderName.equals("SYS")) { + expectedLoader = SYS_LOADER; + } else if (loaderName.equals("EXT")) { + expectedLoader = PLATFORM_LOADER; + } else if (loaderName.equals("BOOT")) { + expectedLoader = BOOT_LOADER; + } + + System.out.println(testName + ": class=" + className + " shouldLoad=" + + shouldLoadName + " by loader:" + expectedLoader); + + // Try to load the specified class with the default ClassLoader. + Class clazz = null; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + System.out.println(e); + } + + if (clazz != null) { + // class loaded + if (shouldLoad) { + // Make sure we got the expected defining ClassLoader + ClassLoader actualLoader = clazz.getClassLoader(); + if (actualLoader != expectedLoader) { + throw new RuntimeException(testName + " FAILED: " + clazz + " loaded by " + actualLoader + + ", expected " + expectedLoader); + } + // Make sure we got the right version of the class. toString() of an instance + // of the overridden version of the class should return "hi". + String s = clazz.newInstance().toString(); + if (!s.equals("hi")) { + throw new RuntimeException(testName + " FAILED: toString() returned \"" + s + + "\" instead of \"hi\"" ); + } + System.out.println(testName + " PASSED: class loaded as expected."); + } else { + throw new RuntimeException(testName + " FAILED: class loaded, but should have failed to load."); + } + } else { + // class did not load + if (shouldLoad) { + throw new RuntimeException(testName + " FAILED: class failed to load."); + } else { + System.out.println(testName + " PASSED: ClassNotFoundException thrown as expected"); + } + } + } + + static void assertTrue(boolean expr) { + if (!expr) + throw new RuntimeException("assertion failed"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/sun/nio/cs/ext/MyClass.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/sun/nio/cs/ext/MyClass.java new file mode 100644 index 00000000000..92e9204dce2 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/sun/nio/cs/ext/MyClass.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015, 2017, 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.nio.cs.ext; + +public class MyClass { + public String toString() { + return "hi"; + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/sun/nio/cs/ext1/MyClass.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/sun/nio/cs/ext1/MyClass.java new file mode 100644 index 00000000000..43b24f598ee --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/sun/nio/cs/ext1/MyClass.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015, 2017, 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.nio.cs.ext1; + +public class MyClass { + public String toString() { + return "hi"; + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java new file mode 100644 index 00000000000..cb30412bae4 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +/** + * Used with -p or --upgrade-module-path to exercise the replacement + * of classes in modules that are linked into the runtime image. + */ + +import java.lang.*; +import java.lang.reflect.*; +import sun.hotspot.WhiteBox; + + +public class LimitModsHelper { + static final ClassLoader PLATFORM_LOADER = ClassLoader.getPlatformClassLoader(); + static final ClassLoader SYS_LOADER = ClassLoader.getSystemClassLoader(); + + public static void main(String[] args) throws Exception { + assertTrue(args.length == 4); + String[] classNames = new String[3]; + for (int i = 0; i < 3; i++) { + classNames[i] = args[i].replace('/', '.'); + } + int excludeModIdx = Integer.parseInt(args[3]); + + ClassLoader expectedLoaders[] = {null, PLATFORM_LOADER, SYS_LOADER}; + + WhiteBox wb = WhiteBox.getWhiteBox(); + + Class clazz = null; + for (int i = 0; i < 3; i++) { + try { + // Load the class with the default ClassLoader. + clazz = Class.forName(classNames[i]); + } catch (Exception e) { + if (i == excludeModIdx) { + System.out.println(classNames[i] + " not found as expected because the module isn't in the --limit-modules - PASSED"); + } else { + throw(e); + } + } + + if (clazz != null && i != excludeModIdx) { + // Make sure we got the expected defining ClassLoader + testLoader(clazz, expectedLoaders[i]); + + // Make sure the class is in the shared space + if (!wb.isSharedClass(clazz)) { + throw new RuntimeException(clazz.getName() + + ".class should be in the shared space. " + + "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName()); + } + } + clazz = null; + } + } + + /** + * Asserts that given class has the expected defining loader. + */ + static void testLoader(Class clazz, ClassLoader expected) { + ClassLoader loader = clazz.getClassLoader(); + if (loader != expected) { + throw new RuntimeException(clazz + " loaded by " + loader + ", expected " + expected); + } + } + + static void assertTrue(boolean expr) { + if (!expr) + throw new RuntimeException("assertion failed"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java new file mode 100644 index 00000000000..434ddfcfae6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library ../.. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules jdk.jartool/sun.tools.jar + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @compile LimitModsHelper.java + * @compile ../../test-classes/java/net/HttpCookie.jasm + * @compile ../../test-classes/jdk/dynalink/DynamicLinker.jasm + * @compile ../../test-classes/com/sun/tools/javac/Main.jasm + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main LimitModsTests + * @summary AppCDS tests for excluding class in module by using --limit-modules. + */ + +/** + * This is for testing the --limit-modules option with AppCDS. + * This test assumes the following defining class loader, module, class relations: + * class loader module class + * ----------------------------------------------------- + * boot java.base java/net/HttpCookie + * platform jdk.dynalink jdk/dynalink/DynamicLinker + * app jdk.compiler com/sun/tools/javac/Main + * + * This test dumps the above 3 classes into a shared archive. + * Then it will run the following 4 -limit-modules scenarios: + * 1. without --limit-modules + * All 3 classes should be loaded successfully. + * All 3 classes should be loaded by the appropriate class loader. + * All 3 classes should be found in the shared archive. + * 2. --limit-modules java.base,jdk.dynalink + * The loading of the com/sun/tools/javac/Main class should fail. + * The other 2 classes should be loaded successfully and by the appropriate class loader. + * The other 2 classes should be found in the shared archive. + * 3. --limit-modules java.base,jdk.compiler + * The loading of the jdk/nio/dynalink/DynamicLinker class should fail. + * The other 2 classes should be loaded successfully and by the appropriate class loader. + * The other 2 classes should be found in the shared archive. + * 4. --limit-modules jdk.dynalink,jdk.compiler + * The java.base module can't be excluded. + * The results for this case is the same as for case #1. + */ + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + + +public class LimitModsTests { + + // the module that is limited + private static final String[] LIMIT_MODULES = {"java.base", "jdk.dynalink", "jdk.compiler"}; + + // test classes to archive. + private static final String BOOT_ARCHIVE_CLASS = "java/net/HttpCookie"; + private static final String PLATFORM_ARCHIVE_CLASS = "jdk/dynalink/DynamicLinker"; + private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/Main"; + private static final String[] ARCHIVE_CLASSES = { + BOOT_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, APP_ARCHIVE_CLASS}; + private String bootClassPath = null; + private String whiteBoxJar = null; + private String helperJar = null; + private String appJar = null; + private OutputAnalyzer output = null; + + public static void main(String[] args) throws Exception { + LimitModsTests tests = new LimitModsTests(); + tests.dumpArchive(); + tests.runTestNoLimitMods(); + tests.runTestLimitMods(); + } + + void dumpArchive() throws Exception { + JarBuilder.build("limitModsTest", BOOT_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, APP_ARCHIVE_CLASS); + JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + JarBuilder.build("limitModsHelper", "LimitModsHelper"); + + appJar = TestCommon.getTestJar("limitModsTest.jar"); + whiteBoxJar = TestCommon.getTestJar("WhiteBox.jar"); + helperJar = TestCommon.getTestJar("limitModsHelper.jar"); + bootClassPath = "-Xbootclasspath/a:" + whiteBoxJar; + // Dump the test classes into the archive + OutputAnalyzer output1 = TestCommon.dump(appJar, TestCommon.list(ARCHIVE_CLASSES), bootClassPath); + TestCommon.checkDump(output1); + // Make sure all the classes where successfully archived. + for (String archiveClass : ARCHIVE_CLASSES) { + output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass); + } + } + + // run the test without --limit-modules + public void runTestNoLimitMods() throws Exception { + output = TestCommon.exec( + appJar + File.pathSeparator + helperJar, + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", bootClassPath, + "LimitModsHelper", + BOOT_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, APP_ARCHIVE_CLASS, "-1"); // last 4 args passed to test + TestCommon.checkExec(output); + } + + // run the test with --limit-modules + // + // --limit-modules jdk.dynalink,jdk.compiler + // It seems we can't exclude the java.base module. For this case, + // although the java.base module isn't in --limit-modules, the class + // in the java.base module (java.net.HttpCookie) can also be found. + // + // --limit-modules java.base,jdk.dynalink + // --limit-modules java.base,jdk.compiler + public void runTestLimitMods() throws Exception { + String limitMods = null; + for (int excludeModIdx = 0; excludeModIdx < 3; excludeModIdx++) { + for (int includeModIdx = 0; includeModIdx < 3; includeModIdx++) { + if (includeModIdx != excludeModIdx) { + if (limitMods != null) { + limitMods += ","; + limitMods += LIMIT_MODULES[includeModIdx]; + } else { + limitMods = LIMIT_MODULES[includeModIdx]; + } + } + } + output = TestCommon.exec( + appJar + File.pathSeparator + helperJar, + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", bootClassPath, + "--limit-modules", limitMods, + "LimitModsHelper", + BOOT_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, APP_ARCHIVE_CLASS, + Integer.toString(excludeModIdx)); // last 4 args passed to test + TestCommon.checkExec(output); + limitMods = null; + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/OverrideTests.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/OverrideTests.java new file mode 100644 index 00000000000..42355b73ec2 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/OverrideTests.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2015, 2017, 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 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @modules java.base/jdk.internal.misc + * @library ../.. + * @library /test/lib + * @run main OverrideTests + * @summary AppCDS tests for overriding archived classes with -p and --upgrade-module-path + */ + +/* + * This test consists of 4 tests: + * 1. Archive PLATFORM class and override with --upgrade-module-path. + * 2. Archive PLATFORM class and override with -p. + * 3. Archive APP class and override with --upgrade-module-path. + * 4. Archive App class and override with -p. + * For all 4 tests, the class is instantiatied and toString() is called + * to check whether the archived version or the override version was instantiatied. + * For tests 1 and 3, the overridden version should be instantiatied. + * For tests 2 and 4, the archived version should be instantiated. + * + * This test uses the same test helper class in all 4 cases. It is located in + * src/test/jdk/test/Main.java. It will be invoked once for each test cases, + * with parameters to the test determining how it is run and what the + * expected result is. See Main.java for a description of these 3 arguments. + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.Asserts; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + + +public class OverrideTests { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module that is upgraded + private static final String[] UPGRADED_MODULES = {"jdk.compiler", "java.activation"}; + private static final Path[] UPGRADEDMODS_DIR = {Paths.get("upgradedmod1"), Paths.get("upgradedmod2")}; + + // the test module + private static final String TEST_MODULE = "test"; + private static final String MAIN_CLASS = "jdk.test.Main"; + + // test classes to archive. These are both in UPGRADED_MODULES + private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/Main"; + private static final String PLATFORM_ARCHIVE_CLASS = "javax/activation/UnsupportedDataTypeException"; + private static final String[] ARCHIVE_CLASSES = {APP_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS}; + private static String testArchiveName; + + + public static void main(String[] args) throws Exception { + OverrideTests tests = new OverrideTests(); + tests.compileModulesAndDumpArchive(); + tests.testAppClassOverriding(); + tests.testPlatformClassOverriding(); + } + + void compileModulesAndDumpArchive() throws Exception { + boolean compiled; + // javac -d upgradedmods/$upgradedMod src/$upgradedMod/** + int i = 0; + for (String upgradedMod : UPGRADED_MODULES) { + compiled = CompilerUtils.compile( + SRC_DIR.resolve(upgradedMod), + UPGRADEDMODS_DIR[i].resolve(upgradedMod) + ); + Asserts.assertTrue(compiled, upgradedMod + " did not compile"); + i++; + } + + // javac -d mods/test --upgrade-module-path upgradedmods ... + compiled = CompilerUtils.compile( + SRC_DIR.resolve(TEST_MODULE), + MODS_DIR.resolve(TEST_MODULE), + "--upgrade-module-path", UPGRADEDMODS_DIR[0].toString() + + System.getProperty("path.separator") + UPGRADEDMODS_DIR[1].toString() + ); + Asserts.assertTrue(compiled, TEST_MODULE + " did not compile"); + + // the java.activation module is not defined by default; --add-modules is required. + // dumping without "--add-modules java.activation" + // the class in the javax.activation package cannot be found + OutputAnalyzer output1 = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES)); + TestCommon.checkDump(output1); + output1.shouldContain( + "Preload Warning: Cannot find javax/activation/UnsupportedDataTypeException"); + + // dump the archive with jdk.comiler and java.activation classes in the class list + // with "--add-modules java.activation" + output1 = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES), + "--add-modules", "java.activation"); + TestCommon.checkDump(output1); + // Make sure all the classes where successfully archived. + for (String archiveClass : ARCHIVE_CLASSES) { + output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass); + } + + testArchiveName = TestCommon.getCurrentArchiveName(); + } + + /** + * APP Class Overriding Tests + * + * Archive APP class com.sun.tools.javac.Main from module jdk.compiler. + * -At run time, upgrade module jdk.compiler using --upgrade-module-path. + * Class.forname(Main) MUST NOT load the archived Main. + * -At run time, module jdk.compiler also exists in --module-path. + * Class.forname(Main) MUST load the archived Main. + */ + public void testAppClassOverriding() throws Exception { + testClassOverriding(APP_ARCHIVE_CLASS, "app"); + } + + /** + * PLATFORM Class Overriding Tests + * + * Archive PLATFORM class javax.activation.UnsupportedDataTypeException from module jdk.activation. + * -At run time, upgrade module jdk.activation using --upgrade-module-path. + * Class.forname(UnsupportedDataTypeException) MUST NOT load the archived UnsupportedDataTypeException. + * -At run time, module jdk.activation also exists in --module-path. + * Class.forname(UnsupportedDataTypeException) MUST load the archived UnsupportedDataTypeException. + */ + public void testPlatformClassOverriding() throws Exception { + testClassOverriding(PLATFORM_ARCHIVE_CLASS, "platform"); + } + + /** + * Run the test twice. Once with upgrade module on --upgrade-module-path and once with it on -p. + * Only modules defined to the PlatformClassLoader are upgradeable. + * Modules defined to the AppClassLoader are not upgradeble; we expect the + * FindException to be thrown. + */ + void testClassOverriding(String archiveClass, String loaderName) throws Exception { + String mid = TEST_MODULE + "/" + MAIN_CLASS; + OutputAnalyzer output; + boolean isAppLoader = loaderName.equals("app"); + int upgradeModIdx = isAppLoader ? 0 : 1; + String expectedException = "java.lang.module.FindException: Unable to compute the hash"; + String prefix[] = new String[4]; + prefix[0] = "-cp"; + prefix[1] = "\"\""; + prefix[2] = "--add-modules"; + prefix[3] = "java.activation"; + + // Run the test with --upgrade-module-path set to alternate location of archiveClass + // The alternate version of archiveClass SHOULD be found. + output = TestCommon.execModule( + prefix, + UPGRADEDMODS_DIR[upgradeModIdx].toString(), + MODS_DIR.toString(), + mid, + archiveClass, loaderName, "true"); // last 3 args passed to test + if (isAppLoader) { + try { + output.shouldContain(expectedException); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + } else { + TestCommon.checkExec(output); + } + + // Now run this same test again, but this time without AppCDS. Behavior should be the same. + CDSOptions opts = (new CDSOptions()) + .addPrefix(prefix) + .setArchiveName(testArchiveName).setUseVersion(false) + .addSuffix("--upgrade-module-path", UPGRADEDMODS_DIR[upgradeModIdx].toString(), + "-p", MODS_DIR.toString(), "-m", mid) + .addSuffix(archiveClass, loaderName, "true"); + + output = CDSTestUtils.runWithArchive(opts); + + if (isAppLoader) { + try { + output.shouldContain(expectedException); + } catch (Exception e) { + TestCommon.checkCommonExecExceptions(output, e); + } + } else { + if (!CDSTestUtils.isUnableToMap(output)) + output.shouldHaveExitValue(0); + } + + // Run the test with -p set to alternate location of archiveClass. + // The alternate version of archiveClass SHOULD NOT be found. + output = TestCommon.execModule( + prefix, + null, + UPGRADEDMODS_DIR[upgradeModIdx].toString() + java.io.File.pathSeparator + MODS_DIR.toString(), + mid, + archiveClass, loaderName, "false"); // last 3 args passed to test + TestCommon.checkExec(output); + + // Now run this same test again, but this time without AppCDS. Behavior should be the same. + opts = (new CDSOptions()) + .addPrefix(prefix) + .setArchiveName(testArchiveName).setUseVersion(false) + .addSuffix("-p", MODS_DIR.toString(), "-m", mid) + .addSuffix(archiveClass, loaderName, "false"); // params to the test class + + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + if (!CDSTestUtils.isUnableToMap(out)) + out.shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/javax/activation/UnsupportedDataTypeException.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/javax/activation/UnsupportedDataTypeException.java new file mode 100644 index 00000000000..3016bb41a10 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/javax/activation/UnsupportedDataTypeException.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, 2017, 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 javax.activation; + +import java.io.IOException; + +public class UnsupportedDataTypeException extends IOException { + public UnsupportedDataTypeException() { + } + + public String toString() { + return "hi"; + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/module-info.java new file mode 100644 index 00000000000..23c707a46f7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/module-info.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +module java.activation { + exports javax.activation; +} + diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/jdk.compiler/com/sun/tools/javac/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/jdk.compiler/com/sun/tools/javac/Main.java new file mode 100644 index 00000000000..f535ccd034a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/jdk.compiler/com/sun/tools/javac/Main.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015, 2017, 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 com.sun.tools.javac; + +public class Main { + public String toString() { + return "hi"; + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/jdk.compiler/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/jdk.compiler/module-info.java new file mode 100644 index 00000000000..a9c236d7bac --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/jdk.compiler/module-info.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +module jdk.compiler { + exports com.sun.tools.javac; +} + diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/jdk/test/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/jdk/test/Main.java new file mode 100644 index 00000000000..e752f4d3da5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/jdk/test/Main.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +/** + * Used with -p or --upgrade-module-path to exercise the replacement + * of classes in modules that are linked into the runtime image. + */ + +package jdk.test; + +public class Main { + static final ClassLoader PLATFORM_LOADER = ClassLoader.getPlatformClassLoader(); + static final ClassLoader SYS_LOADER = ClassLoader.getSystemClassLoader(); + + public static void main(String[] args) throws Exception { + ClassLoader loader = null; + boolean shouldOverride = false; + + /* + * 3 Arguments are passed to this test: + * 1. className: Name of the class to load. + * 2. loaderName: Either "platform" or "app", which specifies which ClassLoader is expected + * to be the defining ClassLoader once the class is loaded. The initiating + * ClassLoader is always the default ClassLoader (which should be the + * app (system) ClassLoader. + * 3. shouldOverride: Either "true" or "false" to indicate whether the loaded class + * should be the one we are attempting to override with (not the archived version). + */ + + assertTrue(args.length == 3, "Unexpected number of arguments: expected 3, actual " + args.length); + String className = args[0].replace('/', '.'); + String loaderName = args[1]; // "platform" or "app" + String shouldOverrideName = args[2]; // "true" or "false" + + if (loaderName.equals("app")) { + loader = SYS_LOADER; + } else if (loaderName.equals("platform")) { + loader = PLATFORM_LOADER; + } else { + assertTrue(false); + } + + if (shouldOverrideName.equals("true")) { + shouldOverride = true; + } else if (shouldOverrideName.equals("false")) { + shouldOverride = false; + } else { + assertTrue(false); + } + + // Load the class with the default ClassLoader. + Class clazz = Class.forName(className, true, loader); + // Make sure we got the expected defining ClassLoader + testLoader(clazz, loader); + // Create an instance and see what toString() returns + String s = clazz.newInstance().toString(); + // The overridden version of the class should return "hi". Make sure + // it does only if we are expecting to have loaded the overridden version. + assertTrue(s.equals("hi") == shouldOverride); + } + + /** + * Asserts that given class has the expected defining loader. + */ + static void testLoader(Class clazz, ClassLoader expected) { + ClassLoader loader = clazz.getClassLoader(); + if (loader != expected) { + throw new RuntimeException(clazz + " loaded by " + loader + ", expected " + expected); + } + } + + static void assertTrue(boolean expr) { + assertTrue(expr, ""); + } + + static void assertTrue(boolean expr, String msg) { + if (!expr) + throw new RuntimeException("assertion failed: " + msg); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/module-info.java new file mode 100644 index 00000000000..8ca8942555b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/module-info.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +module test { + requires jdk.compiler; + requires java.activation; +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/ClassFileLoadHook.java b/test/hotspot/jtreg/runtime/appcds/jvmti/ClassFileLoadHook.java new file mode 100644 index 00000000000..7d564caa8d1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/ClassFileLoadHook.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +class LoadMe { + static String getValue() { + return "beforeHook"; + } + static String getOtherValue() { + return "abc-beforeHook-xyz"; + } +} + +public class ClassFileLoadHook { + public enum TestCaseId { + SHARING_OFF_CFLH_ON, // test case to establish a baseline + SHARING_ON_CFLH_OFF, + SHARING_AUTO_CFLH_ON, + SHARING_ON_CFLH_ON + } + + public static void main(String args[]) { + TestCaseId testCase = TestCaseId.valueOf(args[0]); + WhiteBox wb = WhiteBox.getWhiteBox(); + + System.out.println("====== ClassFileLoadHook.main():testCase = " + testCase); + System.out.println("getValue():" + LoadMe.getValue()); + System.out.println("getOtherValue():" + LoadMe.getOtherValue()); + + switch (testCase) { + case SHARING_OFF_CFLH_ON: + assertTrue("after_Hook".equals(LoadMe.getValue()) && + "abc-after_Hook-xyz".equals(LoadMe.getOtherValue()), + "Not sharing, this test should replace beforeHook " + + "with after_Hook"); + break; + + case SHARING_ON_CFLH_OFF: + assertTrue(wb.isSharedClass(LoadMe.class), + "LoadMe should be shared, but is not"); + assertTrue("beforeHook".equals(LoadMe.getValue()) && + "abc-beforeHook-xyz".equals(LoadMe.getOtherValue()), + "CFLH off, bug values are redefined"); + break; + + case SHARING_AUTO_CFLH_ON: + case SHARING_ON_CFLH_ON: + // LoadMe is rewritten on CFLH + assertFalse(wb.isSharedClass(LoadMe.class), + "LoadMe should not be shared if CFLH has modified the class"); + assertFalse("beforeHook".equals(LoadMe.getValue()) && + "abc-beforeHook-xyz".equals(LoadMe.getOtherValue()), + "Class contents should be changed if CFLH is enabled"); + break; + + default: + throw new RuntimeException("Invalid testcase"); + + } + } + + private static void assertTrue(boolean expr, String msg) { + if (!expr) + throw new RuntimeException(msg); + } + + private static void assertFalse(boolean expr, String msg) { + if (expr) + throw new RuntimeException(msg); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/ClassFileLoadHookTest.java b/test/hotspot/jtreg/runtime/appcds/jvmti/ClassFileLoadHookTest.java new file mode 100644 index 00000000000..e62013ba8a3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/ClassFileLoadHookTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, 2017, 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 Test jvmti class file loader hook interaction with AppCDS + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * java.management + * @build ClassFileLoadHook + * @run main/othervm/native ClassFileLoadHookTest + */ + + +import jdk.test.lib.Asserts; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + + +public class ClassFileLoadHookTest { + public static String sharedClasses[] = { + "ClassFileLoadHook", + "ClassFileLoadHook$TestCaseId", + "ClassFileLoadHook$1", + "LoadMe" + }; + + public static void main(String[] args) throws Exception { + String wbJar = + ClassFileInstaller.writeJar("WhiteBox.jar", "sun.hotspot.WhiteBox"); + String appJar = + ClassFileInstaller.writeJar("ClassFileLoadHook.jar", sharedClasses); + String useWb = "-Xbootclasspath/a:" + wbJar; + + // First, run the test class directly, w/o sharing, as a baseline reference + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + useWb, + "-agentlib:SimpleClassFileLoadHook=LoadMe,beforeHook,after_Hook", + "ClassFileLoadHook", + "" + ClassFileLoadHook.TestCaseId.SHARING_OFF_CFLH_ON); + TestCommon.executeAndLog(pb, "no-sharing").shouldHaveExitValue(0); + + // Run with AppCDS, but w/o CFLH - second baseline + TestCommon.testDump(appJar, sharedClasses, useWb); + OutputAnalyzer out = TestCommon.exec(appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", useWb, + "ClassFileLoadHook", + "" + ClassFileLoadHook.TestCaseId.SHARING_ON_CFLH_OFF); + + TestCommon.checkExec(out); + + + // Now, run with AppCDS with -Xshare:auto and CFLH + out = TestCommon.execAuto("-cp", appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", useWb, + "-agentlib:SimpleClassFileLoadHook=LoadMe,beforeHook,after_Hook", + "ClassFileLoadHook", + "" + ClassFileLoadHook.TestCaseId.SHARING_AUTO_CFLH_ON); + + CDSOptions opts = (new CDSOptions()).setXShareMode("auto"); + TestCommon.checkExec(out, opts); + + // Now, run with AppCDS -Xshare:on and CFLH + out = TestCommon.exec(appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", useWb, + "-agentlib:SimpleClassFileLoadHook=LoadMe,beforeHook,after_Hook", + "ClassFileLoadHook", + "" + ClassFileLoadHook.TestCaseId.SHARING_ON_CFLH_ON); + TestCommon.checkExec(out); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationAgent.mf b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationAgent.mf new file mode 100644 index 00000000000..58dcf797de6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationAgent.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Premain-Class: InstrumentationRegisterClassFileTransformer +Agent-Class: InstrumentationRegisterClassFileTransformer +Can-Retransform-Classes: true +Can-Redefine-Classes: true diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java new file mode 100644 index 00000000000..1328f583031 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.instrument.ClassDefinition; +import java.lang.instrument.Instrumentation; +import java.lang.instrument.UnmodifiableClassException; +import java.net.URL; +import java.net.URLClassLoader; +import java.io.File; +import java.security.CodeSigner; +import java.security.CodeSource; +import java.security.ProtectionDomain; +import sun.hotspot.WhiteBox; + +public class InstrumentationApp { + static WhiteBox wb = WhiteBox.getWhiteBox(); + + public static final String COO_CLASS_NAME = "InstrumentationApp$Coo"; + + public static interface Intf { // Loaded from Boot class loader (-Xbootclasspath/a). + public String get(); + } + public static class Bar implements Intf { // Loaded from Boot class loader. + public String get() { + // The initial transform: + // change "buzz" -> "fuzz" + // The re-transform: + // change "buzz" -> "guzz" + return "buzz"; + } + } + public static class Foo implements Intf { // Loaded from AppClassLoader, or from a custom loader + public String get() { + // The initial transform: + // change "buzz" -> "fuzz" + // The re-transform: + // change "buzz" -> "guzz" + return "buzz"; + } + } + public static class Coo implements Intf { // Loaded from custom class loader. + public String get() { + // The initial transform: + // change "buzz" -> "fuzz" + // The re-transform: + // change "buzz" -> "guzz" + return "buzz"; + } + } + + // This class file should be archived if AppCDSv2 is enabled on this platform. See + // the comments around the call to TestCommon.dump in InstrumentationTest.java. + public static class ArchivedIfAppCDSv2Enabled {} + + public static boolean isAppCDSV2Enabled() { + return wb.isSharedClass(ArchivedIfAppCDSv2Enabled.class); + } + + public static class MyLoader extends URLClassLoader { + public MyLoader(URL[] urls, ClassLoader parent, File jar) { + super(urls, parent); + this.jar = jar; + } + File jar; + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + synchronized (getClassLoadingLock(name)) { + // First, check if the class has already been loaded + Class clz = findLoadedClass(name); + if (clz != null) { + return clz; + } + + if (name.equals(COO_CLASS_NAME)) { + try { + byte[] buff = Util.getClassFileFromJar(jar, name); + return defineClass(name, buff, 0, buff.length); + } catch (Throwable t) { + t.printStackTrace(); + throw new RuntimeException("Unexpected", t); + } + } + } + return super.loadClass(name, resolve); + } + } + + static int numTests = 0; + static int failed = 0; + static boolean isAttachingAgent = false; + static Instrumentation instrumentation; + + public static void main(String args[]) throws Throwable { + System.out.println("INFO: AppCDSv1 " + (wb.isSharedClass(InstrumentationApp.class) ? "enabled" :"disabled")); + System.out.println("INFO: AppCDSv2 " + (isAppCDSV2Enabled() ? "enabled" : "disabled")); + + File bootJar = new File(args[0]); + File appJar = new File(args[1]); + File custJar = new File(args[2]); + String flagFile = args[3]; + waitAttach(flagFile); + + instrumentation = InstrumentationRegisterClassFileTransformer.getInstrumentation(); + System.out.println("INFO: instrumentation = " + instrumentation); + + testBootstrapCDS("Bootstrap Loader", bootJar); + testAppCDSv1("Application Loader", appJar); + + if (isAppCDSV2Enabled()) { + testAppCDSv2("Custom Loader (unregistered)", custJar); + } + + if (failed > 0) { + throw new RuntimeException("FINAL RESULT: " + failed + " out of " + numTests + " test case(s) have failed"); + } else { + System.out.println("FINAL RESULT: All " + numTests + " test case(s) have passed!"); + } + } + + static void waitAttach(String flagFile) throws Throwable { + if (!flagFile.equals("noattach")) { + File f = new File(flagFile); + long start = System.currentTimeMillis(); + while (f.exists()) { + long elapsed = System.currentTimeMillis() - start; + System.out.println(".... (" + elapsed + ") waiting for deletion of " + f); + Thread.sleep(1000); + } + System.out.println("Attach succeeded (child)"); + isAttachingAgent = true; + } + } + + static void testBootstrapCDS(String group, File jar) throws Throwable { + doTest(group, new Bar(), jar); + } + + static void testAppCDSv1(String group, File jar) throws Throwable { + doTest(group, new Foo(), jar); + } + + static void testAppCDSv2(String group, File jar) throws Throwable { + URL[] urls = new URL[] {jar.toURI().toURL()}; + MyLoader loader = new MyLoader(urls, InstrumentationApp.class.getClassLoader(), jar); + Class klass = loader.loadClass(COO_CLASS_NAME); + doTest(group, (Intf)klass.newInstance(), jar); + } + + static void doTest(String group, Intf object, File jar) throws Throwable { + Class klass = object.getClass(); + System.out.println(); + System.out.println("++++++++++++++++++++++++++"); + System.out.println("Test group: " + group); + System.out.println("Testing with classloader = " + klass.getClassLoader()); + System.out.println("Testing with class = " + klass); + System.out.println("++++++++++++++++++++++++++"); + + // Initial transform + String f = object.get(); + assertTrue(f.equals("fuzz"), "object.get(): Initial transform should give 'fuzz'", f); + + // Retransform + f = "(failed)"; + try { + instrumentation.retransformClasses(klass); + f = object.get(); + } catch (UnmodifiableClassException|UnsupportedOperationException e) { + e.printStackTrace(); + } + assertTrue(f.equals("guzz"), "object.get(): retransformation should give 'guzz'", f); + + // Redefine + byte[] buff = Util.getClassFileFromJar(jar, klass.getName()); + Util.replace(buff, "buzz", "huzz"); + f = "(failed)"; + try { + instrumentation.redefineClasses(new ClassDefinition(klass, buff)); + f = object.get(); + } catch (UnmodifiableClassException|UnsupportedOperationException e) { + e.printStackTrace(); + } + assertTrue(f.equals("quzz"), "object.get(): redefinition should give 'quzz'", f); + + System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++ (done)\n\n"); + } + + private static void assertTrue(boolean expr, String msg, String string) { + numTests ++; + System.out.printf("Test case %2d ", numTests); + + if (expr) { + System.out.println("PASSED: " + msg + " and we got '" + string + "'"); + } else { + failed ++; + System.out.println("FAILED: " + msg + " but we got '" + string + "'"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationClassFileTransformer.java b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationClassFileTransformer.java new file mode 100644 index 00000000000..64eabbaf003 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationClassFileTransformer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.security.ProtectionDomain; + +// Note: Util is from /test/hotspot/jtreg/runtime/appcds/test-classes/TestCommon.java + +public class InstrumentationClassFileTransformer implements ClassFileTransformer { + public byte[] transform(ClassLoader loader, String name, Class classBeingRedefined, + ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException { + + if (name.startsWith("InstrumentationApp$") && !name.equals("InstrumentationApp$NotTransformed")) { + System.out.println("Transforming: " + name + " class = " + classBeingRedefined); + try { + if (classBeingRedefined == null) { + // Initial transform + replace(buffer, "buzz", "fuzz"); + } else { + replace(buffer, "buzz", "guzz"); // Retransform + replace(buffer, "huzz", "quzz"); // Redefine + } + } catch (Throwable t) { + t.printStackTrace(); + } + return buffer; + } + return null; + } + + static void replace(byte[] buffer, String from, String to) { + int n = Util.replace(buffer, from, to); + System.out.println("..... replaced " + n + " occurrence(s) of '" + from + "' to '" + to + "'"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationRegisterClassFileTransformer.java b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationRegisterClassFileTransformer.java new file mode 100644 index 00000000000..2d2aec74269 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationRegisterClassFileTransformer.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.Instrumentation; + +// This class is available on the classpath so it can be accessed by InstrumentationApp +public class InstrumentationRegisterClassFileTransformer { + private static Instrumentation savedInstrumentation; + + public static void premain(String agentArguments, Instrumentation instrumentation) { + System.out.println("InstrumentationRegisterClassFileTransformer.premain() is called"); + instrumentation.addTransformer(new InstrumentationClassFileTransformer(), /*canRetransform=*/true); + savedInstrumentation = instrumentation; + } + + public static Instrumentation getInstrumentation() { + return savedInstrumentation; + } + + public static void agentmain(String args, Instrumentation inst) throws Exception { + premain(args, inst); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java new file mode 100644 index 00000000000..1e869c28929 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2014, 2017, 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 Exercise the java.lang.instrument.Instrumentation APIs on classes archived + * using CDS/AppCDSv1/AppCDSv2. + * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.flavor != "minimal" + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * java.management + * @build sun.hotspot.WhiteBox + * InstrumentationApp + * InstrumentationClassFileTransformer + * InstrumentationRegisterClassFileTransformer + * @run main/othervm InstrumentationTest + */ + +// Note: TestCommon is from /test/hotspot/jtreg/runtime/appcds/TestCommon.java +// Note: Util is from /test/hotspot/jtreg/runtime/appcds/test-classes/TestCommon.java + +import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.VirtualMachineDescriptor; +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import jdk.test.lib.Asserts; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class InstrumentationTest { + public static String bootClasses[] = { + "InstrumentationApp$Intf", + "InstrumentationApp$Bar", + "sun.hotspot.WhiteBox", + }; + public static String appClasses[] = { + "InstrumentationApp", + "InstrumentationApp$Foo", + "InstrumentationApp$MyLoader", + }; + public static String custClasses[] = { + "InstrumentationApp$Coo", + }; + public static String sharedClasses[] = TestCommon.concat(bootClasses, appClasses); + + public static String agentClasses[] = { + "InstrumentationClassFileTransformer", + "InstrumentationRegisterClassFileTransformer", + "Util", + }; + + public static void main(String[] args) throws Throwable { + runTest(false); + runTest(true); + } + + public static void runTest(boolean attachAgent) throws Throwable { + String bootJar = + ClassFileInstaller.writeJar("InstrumentationBoot.jar", bootClasses); + String appJar = + ClassFileInstaller.writeJar("InstrumentationApp.jar", + TestCommon.concat(appClasses, + "InstrumentationApp$ArchivedIfAppCDSv2Enabled")); + String custJar = + ClassFileInstaller.writeJar("InstrumentationCust.jar", custClasses); + String agentJar = + ClassFileInstaller.writeJar("InstrumentationAgent.jar", + ClassFileInstaller.Manifest.fromSourceFile("InstrumentationAgent.mf"), + agentClasses); + + String bootCP = "-Xbootclasspath/a:" + bootJar; + + System.out.println(""); + System.out.println("============================================================"); + System.out.println("CDS: NO, attachAgent: " + (attachAgent ? "YES" : "NO")); + System.out.println("============================================================"); + System.out.println(""); + + String agentCmdArg, flagFile; + if (attachAgent) { + // we will attach the agent, so don't specify -javaagent in the command line. We'll use + // something harmless like -showversion to make it easier to construct the command line + agentCmdArg = "-showversion"; + } else { + agentCmdArg = "-javaagent:" + agentJar; + } + + // First, run the test class directly, w/o sharing, as a baseline reference + flagFile = getFlagFile(attachAgent); + AgentAttachThread t = doAttach(attachAgent, flagFile, agentJar); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + bootCP, + "-cp", appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xshare:off", + agentCmdArg, + "InstrumentationApp", bootJar, appJar, custJar, flagFile); + TestCommon.executeAndLog(pb, "no-sharing").shouldHaveExitValue(0); + checkAttach(t); + + // Dump the AppCDS archive. On some platforms AppCDSv2 may not be enabled, so we + // first try the v2 classlist, and if that fails, revert to the v1 classlist. + // Note that the InstrumentationApp$ArchivedIfAppCDSv2Enabled class is archived + // only if V2 is enabled. This is tested by InstrumentationApp.isAppCDSV2Enabled(). + String[] v2Classes = { + "InstrumentationApp$ArchivedIfAppCDSv2Enabled", + "java/lang/Object id: 0", + "InstrumentationApp$Intf id: 1", + "InstrumentationApp$Coo id: 2 super: 0 interfaces: 1 source: " + custJar, + }; + String[] sharedClassesWithV2 = TestCommon.concat(v2Classes, sharedClasses); + OutputAnalyzer out = TestCommon.dump(appJar, sharedClassesWithV2, bootCP); + if (out.getExitValue() != 0) { + System.out.println("Redumping with AppCDSv2 disabled"); + TestCommon.testDump(appJar, sharedClasses, bootCP); + } + + // Run with AppCDS. + System.out.println(""); + System.out.println("============================================================"); + System.out.println("CDS: YES, attachAgent: " + (attachAgent ? "YES" : "NO")); + System.out.println("============================================================"); + System.out.println(""); + + flagFile = getFlagFile(attachAgent); + t = doAttach(attachAgent, flagFile, agentJar); + out = TestCommon.execAuto("-cp", appJar, + bootCP, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + agentCmdArg, + "InstrumentationApp", bootJar, appJar, custJar, flagFile); + + CDSOptions opts = (new CDSOptions()).setXShareMode("auto"); + TestCommon.checkExec(out, opts); + checkAttach(t); + } + + static int flagFileSerial = 1; + static private String getFlagFile(boolean attachAgent) { + if (attachAgent) { + // Do not reuse the same file name as Windows may fail to + // delete the file. + return "attach.flag." + ProcessHandle.current().pid() + + "." + (flagFileSerial++) + "." + System.currentTimeMillis(); + } else { + return "noattach"; + } + } + + static AgentAttachThread doAttach(boolean attachAgent, String flagFile, String agentJar) throws Throwable { + if (!attachAgent) { + return null; + } + + // We use the flagFile to prevent the child process to make progress, until we have + // attached to it. + File f = new File(flagFile); + FileOutputStream o = new FileOutputStream(f); + o.write(1); + o.close(); + if (!f.exists()) { + throw new RuntimeException("Failed to create " + f); + } + + // At this point, the child process is not yet launched. Note that + // TestCommon.exec() and OutputAnalyzer.OutputAnalyzer() both block + // until the child process has finished. + // + // So, we will launch a AgentAttachThread which will poll the system + // until the child process is launched, and then do the attachment. + // The child process is uniquely identified by having flagFile in its + // command-line -- see AgentAttachThread.getPid(). + AgentAttachThread t = new AgentAttachThread(flagFile, agentJar); + t.start(); + return t; + } + + static void checkAttach(AgentAttachThread thread) throws Throwable { + if (thread != null) { + thread.check(); + } + } + + static class AgentAttachThread extends Thread { + String flagFile; + String agentJar; + volatile boolean succeeded; + + AgentAttachThread(String flagFile, String agentJar) { + this.flagFile = flagFile; + this.agentJar = agentJar; + this.succeeded = false; + } + + static String getPid(String flagFile) throws Throwable { + while (true) { + // Keep polling until the child process has been launched. If for some + // reason the child process fails to launch, this test will be terminated + // by JTREG's time-out mechanism. + Thread.sleep(100); + List vmds = VirtualMachine.list(); + for (VirtualMachineDescriptor vmd : vmds) { + if (vmd.displayName().contains(flagFile) && vmd.displayName().contains("InstrumentationApp")) { + // We use flagFile (which has the PID of this process) as a unique identifier + // to ident the child process, which we want to attach to. + System.out.println("Process found: " + vmd.id() + " " + vmd.displayName()); + return vmd.id(); + } + } + } + } + + public void run() { + try { + String pid = getPid(flagFile); + VirtualMachine vm = VirtualMachine.attach(pid); + System.out.println(agentJar); + vm.loadAgent(agentJar); + } catch (Throwable t) { + t.printStackTrace(); + throw new RuntimeException(t); + } + + // Delete the flagFile to indicate to the child process that we + // have attached to it, so it should proceed. + File f = new File(flagFile); + for (int i=0; i<5; i++) { + // The detele may fail on Windows if the child JVM is checking + // f.exists() at exactly the same time?? Let's do a little + // dance. + f.delete(); + try { + Thread.sleep(10); + } catch (Throwable t) {;} + } + if (f.exists()) { + throw new RuntimeException("Failed to delete " + f); + } + System.out.println("Attach succeeded (parent)"); + succeeded = true; + } + + void check() throws Throwable { + super.join(); + if (!succeeded) { + throw new RuntimeException("Attaching agent to child VM failed"); + } + } + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelClassesTransform.java b/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelClassesTransform.java new file mode 100644 index 00000000000..b7cfe22d5fc --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelClassesTransform.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, 2017, 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. + * + */ + +class ParallelClassTr0 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr1 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr2 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr3 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr4 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr5 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr6 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr7 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr8 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr9 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr10 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr11 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr12 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr13 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr14 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr15 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr16 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr17 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr18 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr19 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr20 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr21 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr22 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr23 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr24 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr25 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr26 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr27 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr28 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr29 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr30 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr31 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr32 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr33 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr34 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr35 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr36 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr37 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr38 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } +class ParallelClassTr39 { public static String testString = ParallelClassesTransform.BEFORE_PATTERN; } + +class ParallelClassesTransform { + public static final int NUMBER_OF_CLASSES = 40; + public static final String BEFORE_PATTERN = "class-transform-check: this-should-be-transformed"; + public static final String AFTER_PATTERN = "class-transform-check: this-has-been--transformed"; +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelLoadAndTransformTest.java b/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelLoadAndTransformTest.java new file mode 100644 index 00000000000..6356e2d4a6d --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelLoadAndTransformTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016, 2017, 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 Load app classes from CDS archive in parallel threads, + * use initial transformation (CFLH) + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * /test/hotspot/jtreg/runtime/appcds/test-classes /test/hotspot/jtreg/runtime/appcds/jvmti + * /test/hotspot/jtreg/testlibrary/jvmti + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * java.instrument + * @build TransformUtil TransformerAgent ParallelLoad + * @run main ParallelLoadAndTransformTest + */ +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class ParallelLoadAndTransformTest { + + public static void main(String[] args) throws Exception { + String prop = "-Dappcds.parallel.transform.mode=cflh"; + String appJar = ClassFileInstaller.writeJar("parallel_load.jar", + getClassList(true)); + String agentJar = prepareAgent(); + + TestCommon.test(appJar, getClassList(false), + "-javaagent:" + agentJar + "=ParallelClassTr.*", + prop, "ParallelLoad"); + } + + + private static String[] getClassList(boolean includeWatchdog) { + List classList = + IntStream.range(0, ParallelClassesTransform.NUMBER_OF_CLASSES) + .mapToObj(i -> "ParallelClassTr" + i) + .collect(Collectors.toList()); + + classList.add("ParallelLoad"); + classList.add("ParallelLoadThread"); + if (includeWatchdog) + classList.add("ParallelLoadWatchdog"); + + return classList.toArray(new String[0]); + } + + + // Agent is the same for all test cases + private static String prepareAgent() throws Exception { + String agentClasses[] = { + "TransformerAgent", + "TransformerAgent$SimpleTransformer", + "TransformUtil" + }; + + String manifest = "../../../../testlibrary/jvmti/TransformerAgent.mf"; + + return ClassFileInstaller.writeJar("TransformerAgent.jar", + ClassFileInstaller.Manifest.fromSourceFile(manifest), + agentClasses); + } + +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformInterfaceImplementorAppCDS.java b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformInterfaceImplementorAppCDS.java new file mode 100644 index 00000000000..4addd099854 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformInterfaceImplementorAppCDS.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 2017, 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 Exercise initial transformation (class file loader hook) + * with CDS/AppCDS with Interface/Implementor pair + * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes + * /test/hotspot/jtreg/runtime/appcds/jvmti /test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability + * /test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses + * /test/hotspot/jtreg/runtime/SharedArchiveFile /test/hotspot/jtreg/testlibrary/jvmti + * /test/hotspot/jtreg/runtime/appcds/customLoader + * /test/hotspot/jtreg/runtime/appcds/customLoader/test-classes + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.flavor != "minimal" + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * java.management + * java.instrument + * @build TransformUtil TransformerAgent Interface Implementor + * @run main/othervm TransformRelatedClassesAppCDS Interface Implementor + */ diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java new file mode 100644 index 00000000000..0ad374471a1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016, 2017, 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. + * + */ + +// Structure of the test: +// TransformRelatedClassesAppCDS -- common main test driver +// Invoked from test driver classes: +// TransformInterfaceAndImplementor, TransformSuperAndSubClasses.java +// prepares test artifacts, launches tests, checks results +// SuperClazz, SubClass -- classes under test +// Interface, Implementor -- classes under test +// TransformerAgent -- an agent that is used when JVM-under-test is executed +// to transform specific strings inside specified classes +// TransformerAgent.mf - accompanies transformer agent +// CustomLoaderApp -- a test "application" that is used to load +// classes-under-test (Parent, Child) via custom class loader, using +// AppCDS-v2 mechanism (unregistered custom loaders, aka FP) +// This "app" is launched in a child process by this driver with sharing on. + +import java.io.File; +import java.util.ArrayList; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +// This class is intended to test 2 parent-child relationships: +// 1. Base Class (parent) and Derived Class (child) +// 2. Interface (parent) and Implementor (child) +// Parameters to main(): parent, child + +public class TransformRelatedClassesAppCDS extends TransformRelatedClasses { + private static void log(String msg, Object... args) { + String msg0 = String.format(msg, args); + System.out.println("TransformRelatedClassesAppCDS: " + msg0); + } + + // Initial Test Matrix: + // (ParentTransformed = true/false, ChildTransformed = true/false) x + // (BootCDS - see open tests, AppCDS-v1, AppCDS-v2-unregistered) + // Total cases: 2 x 4 = 8 + public static void main(String args[]) throws Exception { + TransformRelatedClassesAppCDS test = + new TransformRelatedClassesAppCDS(args[0], args[1]); + + test.prepareAgent(agentClasses); + + // Test Table + // testCaseId | transformParent | tranformChild | isParentExpectedShared | isChildExpectedShared + ArrayList testTable = new ArrayList<>(); + + // base case - no tranformation - all expected to be shared + testTable.add(new TestEntry(0, false, false, true, true)); + + // transform parent only - both parent and child should not be shared + testTable.add(new TestEntry(1, true, false, false, false)); + + // transform parent and child - both parent and child should not be shared + testTable.add(new TestEntry(2, true, true, false, false)); + + // transform child only - parent should still be shared, but not child + testTable.add(new TestEntry(3, false, true, true, false)); + + // run the tests + test.runWithAppLoader(testTable); + test.runWithCustomLoader(testTable); + } + + + public TransformRelatedClassesAppCDS(String parent, String child) { + super(parent, child); + + // a trick to get it compiled by jtreg + CustomLoaderApp.ping(); + } + + + private void prepareAgent(String[] agentClasses) throws Exception { + String manifest = "../../../../testlibrary/jvmti/TransformerAgent.mf"; + agentJar = ClassFileInstaller.writeJar("TransformerAgent.jar", + ClassFileInstaller.Manifest.fromSourceFile(manifest), + agentClasses); + } + + + private void runWithAppLoader(ArrayList testTable) throws Exception { + String appJar = writeJar("app", testClasses); + + // create an archive + OutputAnalyzer out = TestCommon.dump(appJar, testClasses); + TestCommon.checkDump(out); + + // execute with archive + for (TestEntry entry : testTable) { + log("runTestWithAppLoader(): testCaseId = %d", entry.testCaseId); + String params = TransformTestCommon.getAgentParams(entry, parent, child); + String agentParam = String.format("-javaagent:%s=%s", agentJar, params); + out = TestCommon.execCommon("-Xlog:class+load=info", "-cp", appJar, + agentParam, child); + + TransformTestCommon.checkResults(entry, out, parent, child); + } + } + + + private String[] getCustomClassList(String loaderType, String customJar) { + String type = child + "-" + loaderType; + + switch (type) { + + case "SubClass-unregistered": + return new String[] { + "CustomLoaderApp", + "java/lang/Object id: 0", + parent + " id: 1 super: 0 source: " + customJar, + child + " id: 2 super: 1 source: " + customJar, + }; + + case "Implementor-unregistered": + return new String[] { + "CustomLoaderApp", + "java/lang/Object id: 0", + parent + " id: 1 super: 0 source: " + customJar, + child + " id: 2 super: 0 interfaces: 1 source: " + customJar, + }; + + default: + throw new IllegalArgumentException("getCustomClassList - wrong type: " + type); + } + } + + + private void runWithCustomLoader(ArrayList testTable) throws Exception { + if (!Platform.areCustomLoadersSupportedForCDS()) { + log("custom loader not supported for this platform" + + " - skipping test case for custom loader"); + return; + } + + String appClasses[] = { + "CustomLoaderApp", + }; + + String customClasses[] = { parent, child }; + + // create jar files: appJar, customJar (for custom loaders to load classes from) + String appJar = writeJar("custldr-app", appClasses); + String customJar = writeJar("custldr-custom", customClasses); + + for (TestEntry entry : testTable) { + log("runTestWithCustomLoader(): testCaseId = %d", entry.testCaseId); + // unregistered (aka FP) case + String[] classList = getCustomClassList("unregistered",customJar); + execAndCheckWithCustomLoader(entry, "unregistered", classList, + appJar, agentJar, customJar); + } + } + + + private void + execAndCheckWithCustomLoader(TestEntry entry, String loaderType, + String[] classList, String appJar, + String agentJar, String customJar) + throws Exception { + + OutputAnalyzer out = TestCommon.dump(appJar, classList); + TestCommon.checkDump(out); + + String agentParam = "-javaagent:" + agentJar + "=" + + TransformTestCommon.getAgentParams(entry, parent, child); + + out = TestCommon.execCommon("-Xlog:class+load=info", + "-cp", appJar, + "--add-opens=java.base/java.security=ALL-UNNAMED", + agentParam, + "CustomLoaderApp", + customJar, loaderType, child); + TransformTestCommon.checkResults(entry, out, parent, child); + } + + + private String writeJar(String type, String[] classes) + throws Exception { + String jarName = String.format("%s-%s.jar", child, type); + return ClassFileInstaller.writeJar(jarName, classes); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformSuperSubAppCDS.java b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformSuperSubAppCDS.java new file mode 100644 index 00000000000..2c631b916e4 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformSuperSubAppCDS.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 2017, 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 Exercise initial transformation (class file loader hook) + * with CDS/AppCDS with SubClass and SuperClass + * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes + * /test/hotspot/jtreg/runtime/appcds/jvmti /test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability + * /test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses + * /test/hotspot/jtreg/runtime/SharedArchiveFile /test/hotspot/jtreg/testlibrary/jvmti + * /test/hotspot/jtreg/runtime/appcds/customLoader + * /test/hotspot/jtreg/runtime/appcds/customLoader/test-classes + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.flavor != "minimal" + * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * java.management + * java.instrument + * @build TransformUtil TransformerAgent SubClass SuperClazz + * @run main/othervm TransformRelatedClassesAppCDS SuperClazz SubClass + */ diff --git a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasic.java b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasic.java new file mode 100644 index 00000000000..943a5257557 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasic.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class RedefineBasic { + + public static String newB = + " class RedefineBasic$B { " + + " public static void okToCallBeforeRedefine() { " + + " throw new RuntimeException(\"newB: okToCallBeforeRedefine is " + + " called after redefinition, test failed\"); }" + + " public static void okToCallAfterRedefine() { " + + " System.out.println(\"newB: okToCallAfterRedefine\"); } " + + " } "; + + + static class B { + public static void okToCallBeforeRedefine() { + System.out.println("okToCallBeforeRedefine"); + } + public static void okToCallAfterRedefine() { + throw new RuntimeException( + "okToCallAfterRedefine is called before redefinition, test failed"); + } + } + + static class SubclassOfB extends B { + public static void testAfterRedefine() { + B.okToCallAfterRedefine(); + } + } + + class Subclass2OfB extends B { + public void testAfterRedefine() { + super.okToCallAfterRedefine(); + } + } + + // verify that a given class is shared, report error if necessary + public static void + verifyClassIsShared(WhiteBox wb, Class c) throws Exception { + if (!wb.isSharedClass(c)) { + throw new RuntimeException( + "This class should be shared but isn't: " + c.getName()); + } else { + System.out.println("The class is shared as expected: " + + c.getName()); + } + } + + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + + verifyClassIsShared(wb, RedefineBasic.class); + verifyClassIsShared(wb, B.class); + verifyClassIsShared(wb, SubclassOfB.class); + verifyClassIsShared(wb, Subclass2OfB.class); + + // (1) Test case: verify that original B works as expected + // and that redefined B is shared and works as expected, + // with new behavior + B.okToCallBeforeRedefine(); + RedefineClassHelper.redefineClass(B.class, newB); + verifyClassIsShared(wb, B.class); + B.okToCallAfterRedefine(); + + // Static subclass of the super: + // 1. Make sure it is still shared + // 2. and it calls the correct super (the redefined one) + verifyClassIsShared(wb, SubclassOfB.class); + SubclassOfB.testAfterRedefine(); + + // Same as above, but for non-static class + verifyClassIsShared(wb, Subclass2OfB.class); + RedefineBasic thisTest = new RedefineBasic(); + thisTest.testSubclass2OfB(); + } + + public void testSubclass2OfB() { + Subclass2OfB sub = new Subclass2OfB(); + sub.testAfterRedefine(); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java new file mode 100644 index 00000000000..396e2cba703 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, 2017, 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 /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to + * make sure class redefinition works with CDS. + * (Note: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * java.base/jdk.internal.misc + * java.management + * @run main RedefineClassHelper + * @build sun.hotspot.WhiteBox RedefineBasic + * @run main RedefineBasicTest + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class RedefineBasicTest { + public static String sharedClasses[] = { + "RedefineBasic", + "RedefineBasic$B", + "RedefineBasic$SubclassOfB", + "RedefineBasic$Subclass2OfB", + "RedefineClassHelper", + "jdk/test/lib/compiler/InMemoryJavaCompiler", + "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper", + "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1", + "jdk/test/lib/compiler/InMemoryJavaCompiler$MemoryJavaFileObject" + }; + + public static void main(String[] args) throws Exception { + String wbJar = + ClassFileInstaller.writeJar("WhiteBox.jar", "sun.hotspot.WhiteBox"); + String appJar = + ClassFileInstaller.writeJar("RedefineBasic.jar", sharedClasses); + String useWb = "-Xbootclasspath/a:" + wbJar; + + OutputAnalyzer output; + TestCommon.testDump(appJar, sharedClasses, useWb); + + // redefineagent.jar is created by executing "@run main RedefineClassHelper" + // which should be called before executing RedefineBasicTest + output = TestCommon.exec(appJar, useWb, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-javaagent:redefineagent.jar", + "RedefineBasic"); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java new file mode 100644 index 00000000000..2c2782873a6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, 2017, 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 /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to + * make sure class redefinition works with CDS. + * (Note: AppCDS does not support uncompressed oops) + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * @run main RedefineClassHelper + * @build sun.hotspot.WhiteBox RedefineRunningMethods_SharedHelper + * @run main RedefineRunningMethods_Shared + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class RedefineRunningMethods_Shared { + public static String shared_classes[] = { + "RedefineRunningMethods_Shared", + "RedefineRunningMethods_SharedHelper", + "RedefineRunningMethods", + "RedefineRunningMethods$1", + "RedefineRunningMethods$2", + "RedefineRunningMethods$3", + "RedefineRunningMethods$B", + "RedefineClassHelper", + "jdk/test/lib/compiler/InMemoryJavaCompiler", + "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper", + "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1", + "jdk/test/lib/compiler/InMemoryJavaCompiler$MemoryJavaFileObject" + }; + + public static void main(String[] args) throws Exception { + String wbJar = ClassFileInstaller.writeJar("WhiteBox.jar", "sun.hotspot.WhiteBox"); + String appJar = ClassFileInstaller.writeJar("RedefineRunningMethods_Shared.jar", shared_classes); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + OutputAnalyzer output; + TestCommon.testDump(appJar, shared_classes, + // command-line arguments ... + use_whitebox_jar); + + // RedefineRunningMethods.java contained this: + // @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineRunningMethods + output = TestCommon.exec(appJar, + // command-line arguments ... + use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + // These arguments are expected by RedefineRunningMethods + "-javaagent:redefineagent.jar", + "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace", + "RedefineRunningMethods_SharedHelper"); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_SharedHelper.java b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_SharedHelper.java new file mode 100644 index 00000000000..ff1ffada27b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_SharedHelper.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +/** + * This class is executed by RedefineRunningMethods_Shared.java in + * a sub-process. + */ +public class RedefineRunningMethods_SharedHelper { + public static void main(String[] args) throws Exception { + // (1) Validate that all classes used by RedefineRunningMethods are all shared. + WhiteBox wb = WhiteBox.getWhiteBox(); + for (String name : RedefineRunningMethods_Shared.shared_classes) { + name = name.replace('/', '.'); + Class c = Class.forName(name); + if (!wb.isSharedClass(c)) { + throw new RuntimeException("Test set-up problem. " + + "This class should be shared but isn't: " + name); + } else { + System.out.println("The class is shared as expected: " + name); + } + } + + // (2) Run the class redefinition test. + RedefineRunningMethods.main(args); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/ExerciseGC.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/ExerciseGC.java new file mode 100644 index 00000000000..7d70f463b4e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/ExerciseGC.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, 2017, 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 Exercise GC with shared strings + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @library /test/hotspot/jtreg/runtime/appcds /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build HelloStringGC sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main ExerciseGC + */ +public class ExerciseGC { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJarAndWhiteBox("HelloStringGC"); + + SharedStringsUtils.dumpWithWhiteBox(TestCommon.list("HelloStringGC"), + "SharedStringsBasic.txt"); + + SharedStringsUtils.runWithArchiveAndWhiteBox("HelloStringGC", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+VerifyBeforeGC"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/ExtraSharedInput.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/ExtraSharedInput.txt new file mode 100644 index 00000000000..5b9257d07e9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/ExtraSharedInput.txt @@ -0,0 +1,7 @@ +VERSION: 1.0 +@SECTION: Symbol +0 -1: +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +11 -1: linkMethod +18 -1: type can't be null +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/FlagCombo.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/FlagCombo.java new file mode 100644 index 00000000000..951f2ec6447 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/FlagCombo.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2017, 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 Test relevant combinations of command line flags with shared strings + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build HelloString + * @run main FlagCombo + */ + +import jdk.test.lib.BuildHelper; + +public class FlagCombo { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJar("HelloString"); + + SharedStringsUtils.dump(TestCommon.list("HelloString"), + "SharedStringsBasic.txt"); + + SharedStringsUtils.runWithArchive("HelloString", "-XX:+UseG1GC"); + + if (BuildHelper.isCommercialBuild()) { + SharedStringsUtils.runWithArchiveAuto("HelloString", "-XX:+UnlockCommercialFeatures", + "-XX:StartFlightRecording=dumponexit=true"); + } + + SharedStringsUtils.runWithArchive("HelloString", "-XX:+UnlockDiagnosticVMOptions", + "-XX:NativeMemoryTracking=detail", "-XX:+PrintNMTStatistics"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloString.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloString.java new file mode 100644 index 00000000000..3c1cbbe4361 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloString.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +public class HelloString { + public static void main(String args[]) { + // Let's reference the string that is in the archive + // Make sure the string below is in the shared string data file (string list) + String testString = "shared_test_string_unique_14325"; + System.out.println("Hello String: " + testString); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloStringGC.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloStringGC.java new file mode 100644 index 00000000000..14732626348 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloStringGC.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class HelloStringGC { + public static String[] array01 = new String[1000]; + public static String[] array02 = new String[1000]; + + public static void main(String args[]) throws RuntimeException { + String testString1 = "shared_test_string_unique_14325"; + String testString2 = "test123"; + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (!wb.isShared(testString1) && !wb.areSharedStringsIgnored()) { + throw new RuntimeException("testString1 is not shared"); + } + + for (int i=0; i<5; i++) { + allocSomeStrings(testString1, testString2); + array01 = null; + array02 = null; + System.gc(); + sleep(300); + array01 = new String[1000]; + array02 = new String[1000]; + } + + wb.fullGC(); + + System.out.println("HelloStringGC: PASS"); + } + + private static void allocSomeStrings(String s1, String s2) { + for (int i = 0; i < 1000; i ++) { + array01[i] = new String(s1); + array02[i] = new String(s2); + } + } + + private static void sleep(int ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + } + } + +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloStringPlus.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloStringPlus.java new file mode 100644 index 00000000000..5129a10ba80 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/HelloStringPlus.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +// A test class to be launched in AppCDS mode, has basic+ +// coverage of string operations + +import sun.hotspot.WhiteBox; + +public class HelloStringPlus { + public static void main(String args[]) { + // Let's reference the string that is in archive + String testString1 = "shared_test_string_unique_14325"; + System.out.println("Hello String: " + testString1); + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (!wb.isShared(testString1) && !wb.areSharedStringsIgnored()) { + throw new RuntimeException("testString1 is not shared"); + } + + // Check other basic string operations + // Interning and equality + String[] testArray = new String[] {"shared_", "test_", "string_", "intern_", "12345"}; + String toBeInterned = ""; + + StringBuilder sb = new StringBuilder(); + for (String s : testArray) { + sb.append(s); + } + toBeInterned = sb.toString(); + + System.out.println("About to intern a string: " + toBeInterned); + toBeInterned.intern(); + + // check equality + if (testString1.equals(toBeInterned)) + throw new RuntimeException("Equality test 1 failed"); + + if (!testString1.equals("shared_test_string" + '_' + "unique_14325")) + throw new RuntimeException("Equality test 2 failed"); + + // Chech the hash code functionality; no special assertions, just make sure + // no crashe or exception occurs + System.out.println("testString1.hashCode() = " + testString1.hashCode()); + + // Check intern() method for "" string + String empty = ""; + String empty_interned = empty.intern(); + if (wb.isShared(empty)) { + throw new RuntimeException("Empty string should not be shared"); + } + if (empty_interned != empty) { + throw new RuntimeException("Different string is returned from intern() for empty string"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java new file mode 100644 index 00000000000..6e71c88dcea --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015, 2017, 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 Test options that are incompatible with use of shared strings + * Also test mismatch in oops encoding between dump time and run time + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (vm.gc=="null") + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build HelloString + * @run main IncompatibleOptions + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; + +public class IncompatibleOptions { + static final String COOPS_DUMP_WARNING = + "Cannot dump shared archive when UseCompressedOops or UseCompressedClassPointers is off"; + static final String COOPS_EXEC_WARNING = + "UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces"; + static final String GC_WARNING = + "Archived java heap is not supported"; + static final String OBJ_ALIGNMENT_MISMATCH = + "The shared archive file's ObjectAlignmentInBytes of .* does not equal the current ObjectAlignmentInBytes of"; + static final String COMPACT_STRING_MISMATCH = + "The shared archive file's CompactStrings setting .* does not equal the current CompactStrings setting"; + + static String appJar; + + public static void main(String[] args) throws Exception { + appJar = JarBuilder.build("IncompatibleOptions", "HelloString"); + + // Uncompressed OOPs + testDump(1, "-XX:+UseG1GC", "-XX:-UseCompressedOops", COOPS_DUMP_WARNING, true); + + // incompatible GCs + testDump(2, "-XX:+UseParallelGC", "", GC_WARNING, false); + testDump(3, "-XX:+UseSerialGC", "", GC_WARNING, false); + testDump(4, "-XX:+UseConcMarkSweepGC", "", GC_WARNING, false); + + // ======= archive with compressed oops, run w/o + testDump(5, "-XX:+UseG1GC", "-XX:+UseCompressedOops", null, false); + testExec(5, "-XX:+UseG1GC", "-XX:-UseCompressedOops", + COOPS_EXEC_WARNING, true); + + // NOTE: No warning is displayed, by design + // Still run, to ensure no crash or exception + testExec(6, "-XX:+UseParallelGC", "", "", false); + testExec(7, "-XX:+UseSerialGC", "", "", false); + testExec(8, "-XX:+UseConcMarkSweepGC", "", "", false); + + // Test various oops encodings, by varying ObjectAlignmentInBytes and heap sizes + testDump(9, "-XX:+UseG1GC", "-XX:ObjectAlignmentInBytes=8", null, false); + testExec(9, "-XX:+UseG1GC", "-XX:ObjectAlignmentInBytes=16", + OBJ_ALIGNMENT_MISMATCH, true); + + // See JDK-8081416 - Oops encoding mismatch with shared strings + // produces unclear or incorrect warning + // Correct the test case once the above is fixed + // @ignore JDK-8081416 - for tracking purposes + // for now, run test as is until the proper behavior is determined + testDump(10, "-XX:+UseG1GC", "-Xmx1g", null, false); + testExec(10, "-XX:+UseG1GC", "-Xmx32g", null, true); + + // CompactStrings must match between dump time and run time + testDump(11, "-XX:+UseG1GC", "-XX:-CompactStrings", null, false); + testExec(11, "-XX:+UseG1GC", "-XX:+CompactStrings", + COMPACT_STRING_MISMATCH, true); + testDump(12, "-XX:+UseG1GC", "-XX:+CompactStrings", null, false); + testExec(12, "-XX:+UseG1GC", "-XX:-CompactStrings", + COMPACT_STRING_MISMATCH, true); + } + + static void testDump(int testCaseNr, String collectorOption, String extraOption, + String expectedWarning, boolean expectedToFail) throws Exception { + + System.out.println("Testcase: " + testCaseNr); + OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("Hello"), + "-XX:+UseCompressedOops", + collectorOption, + "-XX:SharedArchiveConfigFile=" + TestCommon.getSourceFile("SharedStringsBasic.txt"), + extraOption); + + if (expectedWarning != null) + output.shouldContain(expectedWarning); + + if (expectedToFail) { + Asserts.assertNE(output.getExitValue(), 0, + "JVM is expected to fail, but did not"); + } + } + + static void testExec(int testCaseNr, String collectorOption, String extraOption, + String expectedWarning, boolean expectedToFail) throws Exception { + + OutputAnalyzer output; + System.out.println("Testcase: " + testCaseNr); + + // needed, otherwise system considers empty extra option as a + // main class param, and fails with "Could not find or load main class" + if (!extraOption.isEmpty()) { + output = TestCommon.exec(appJar, "-XX:+UseCompressedOops", + collectorOption, extraOption, "HelloString"); + } else { + output = TestCommon.exec(appJar, "-XX:+UseCompressedOops", + collectorOption, "HelloString"); + } + + if (expectedWarning != null) + output.shouldMatch(expectedWarning); + + if (expectedToFail) + Asserts.assertNE(output.getExitValue(), 0); + else + SharedStringsUtils.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/InternSharedString.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/InternSharedString.java new file mode 100644 index 00000000000..d64643257d0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/InternSharedString.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, 2017, 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 Test shared strings together with string intern operation + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/hotspot/jtreg/runtime/appcds /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @compile InternStringTest.java + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main InternSharedString + */ + +public class InternSharedString { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJarAndWhiteBox("InternStringTest"); + + SharedStringsUtils.dumpWithWhiteBox(TestCommon.list("InternStringTest"), + "ExtraSharedInput.txt"); + + String[] extraMatches = new String[] { + InternStringTest.passed_output1, + InternStringTest.passed_output2, + InternStringTest.passed_output3 }; + + SharedStringsUtils.runWithArchiveAndWhiteBox(extraMatches, "InternStringTest"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/InternStringTest.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/InternStringTest.java new file mode 100644 index 00000000000..cc95cdf6cbe --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/InternStringTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class InternStringTest { + public static String passed_output1 = "Found shared string."; + public static String passed_output2 = "Shared strings are equal."; + public static String passed_output3 = "Found shared string containing latin1 supplement chars."; + public static String passed_output4 = "Found shared string containing non-western chars."; + public static final String latin1Sup = "XXXX \u00a3 YYYY"; // \u00a3 = The pound sign + public static final String nonWestern = "XXXX \u5678 YYYY"; // \u5678 = Unicode Han Character 'ton (metric or English)' + + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + + // All string literals are shared. + String shared1 = "LiveOak"; + String interned1 = shared1.intern(); + if (wb.areSharedStringsIgnored() || wb.isShared(interned1)) { + System.out.println(passed_output1); + } else { + throw new RuntimeException("Failed: String is not shared."); + } + + // Test 2: shared_string1.intern() == shared_string2.intern() + String shared2 = "LiveOak"; + String interned2 = shared2.intern(); + if (interned1 == interned2) { + System.out.println(passed_output2); + } else { + throw new RuntimeException("Not equal!"); + } + + // Test 3: interned strings with a char in latin1 supplement block [\u0080-\u00ff] + { + String a = "X" + latin1Sup.substring(1); + String b = a.intern(); + + if (wb.areSharedStringsIgnored() || wb.isShared(b)) { + System.out.println(passed_output3); + } else { + throw new RuntimeException("Failed: expected shared string with latin1-supplement chars."); + } + } + + // Test 5: interned strings with non-western characters + { + String a = "X" + nonWestern.substring(1); + String b = a.intern(); + if (wb.areSharedStringsIgnored() || wb.isShared(b)) { + System.out.println(passed_output4); + } else { + throw new RuntimeException("Failed: expected shared string with non-western chars."); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/InvalidFileFormat.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/InvalidFileFormat.java new file mode 100644 index 00000000000..b781f345eed --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/InvalidFileFormat.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, 2017, 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 Check most common errors in file format + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build HelloString + * @run main InvalidFileFormat + */ + +import jdk.test.lib.process.OutputAnalyzer; +import java.io.File; + +// Checking most common error use cases +// This file is not an exhastive test of various shared data file corruption +// Note on usability intent: the shared data file is created and handled by +// the previledge person in the server environment. +public class InvalidFileFormat { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJar("HelloString"); + + test("NonExistentFile.txt", "Unable to get hashtable dump file size"); + test("InvalidHeader.txt", "wrong version of hashtable dump file"); + test("InvalidVersion.txt", "wrong version of hashtable dump file"); + test("CorruptDataLine.txt", "Unknown data type. Corrupted at line 2"); + test("InvalidSymbol.txt", "Unexpected character. Corrupted at line 2"); + test("InvalidSymbolFormat.txt", "Unrecognized format. Corrupted at line 9"); + test("OverflowPrefix.txt", "Num overflow. Corrupted at line 4"); + test("UnrecognizedPrefix.txt", "Unrecognized format. Corrupted at line 5"); + test("TruncatedString.txt", "Truncated. Corrupted at line 3"); + } + + private static void + test(String dataFileName, String expectedWarning) throws Exception { + System.out.println("Filename for testcase: " + dataFileName); + + OutputAnalyzer out = SharedStringsUtils.dumpWithoutChecks(TestCommon.list("HelloString"), + "invalidFormat" + File.separator + dataFileName); + + if (!TestCommon.isUnableToMap(out)) + out.shouldContain(expectedWarning).shouldHaveExitValue(1); + } + +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/LargePages.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LargePages.java new file mode 100644 index 00000000000..a234da4a9df --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LargePages.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015, 2017, 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 Basic shared string test with large pages + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build HelloString + * @run main LargePages + */ +public class LargePages { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJar("HelloString"); + + SharedStringsUtils.dump(TestCommon.list("HelloString"), + "SharedStringsBasic.txt", "-XX:+UseLargePages"); + SharedStringsUtils.runWithArchive("HelloString", "-XX:+UseLargePages"); + + SharedStringsUtils.dump(TestCommon.list("HelloString"), + "SharedStringsBasic.txt", + "-XX:+UseLargePages", "-XX:+UseLargePagesInMetaspace"); + SharedStringsUtils.runWithArchive("HelloString", + "-XX:+UseLargePages", "-XX:+UseLargePagesInMetaspace"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockSharedStrings.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockSharedStrings.java new file mode 100644 index 00000000000..921361ec96a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockSharedStrings.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, 2017, 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 Test locking on shared strings + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/hotspot/jtreg/runtime/appcds /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @compile LockStringTest.java LockStringValueTest.java + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main LockSharedStrings + */ + +public class LockSharedStrings { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJarAndWhiteBox("LockStringTest", "LockStringValueTest"); + + SharedStringsUtils.dumpWithWhiteBox( + TestCommon.list("LockStringTest", "LockStringValueTest"), + "ExtraSharedInput.txt"); + + String[] extraMatch = new String[] {"LockStringTest: PASS"}; + SharedStringsUtils.runWithArchiveAndWhiteBox(extraMatch, "LockStringTest"); + + extraMatch = new String[] {"LockStringValueTest: PASS"}; + SharedStringsUtils.runWithArchiveAndWhiteBox(extraMatch, "LockStringValueTest", + "--add-opens=java.base/java.lang=ALL-UNNAMED"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockStringTest.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockStringTest.java new file mode 100644 index 00000000000..daecd0a93f8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockStringTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class LockStringTest extends Thread { + static String lock = "StringLock"; + static boolean done = false; + + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + if (wb.areSharedStringsIgnored()) { + System.out.println("The shared strings are ignored"); + System.out.println("LockStringTest: PASS"); + return; + } + + if (!wb.isShared(lock)) { + throw new RuntimeException("Failed: String is not shared."); + } + + new LockStringTest().start(); + + synchronized(lock) { + while (!done) { + lock.wait(); + } + } + System.gc(); + System.out.println("LockStringTest: PASS"); + } + + public void run() { + String shared = "LiveOak"; + synchronized (lock) { + for (int i = 0; i < 100; i++) { + new String(shared); + System.gc(); + try { + sleep(5); + } catch (InterruptedException e) {} + } + done = true; + lock.notify(); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockStringValueTest.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockStringValueTest.java new file mode 100644 index 00000000000..4d1e2c1a808 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/LockStringValueTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.reflect.*; +import sun.hotspot.WhiteBox; + +/* + * Lock the 'value' field of a known shared string, java.lang.Object + */ +public class LockStringValueTest { + public static void main(String args[]) { + String s = "LiveOak"; + WhiteBox wb = WhiteBox.getWhiteBox(); + + if (wb.areSharedStringsIgnored()) { + System.out.println("The shared strings are ignored"); + System.out.println("LockStringValueTest: PASS"); + return; + } + + if (!wb.isShared(s)) { + throw new RuntimeException("LockStringValueTest Failed: String is not shared."); + } + + Class c = s.getClass(); + try { + Field f = c.getDeclaredField("value"); + f.setAccessible(true); + Object v = f.get(s); + lock(v); + } catch (NoSuchFieldException nfe) { + } catch (IllegalAccessException iae) {} + } + + public static void lock(Object o) { + synchronized (o) { + System.out.println("LockStringValueTest: PASS"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.java new file mode 100644 index 00000000000..7d9623aa4b7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, 2017, 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 Basic test for shared strings + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/hotspot/jtreg/runtime/appcds /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build HelloString + * @run main SharedStringsBasic + */ +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +// This test does not use SharedStringsUtils intentionally: +// - in order to demonstrate the basic use of the functionality +// - to provide sanity check and catch potential problems in the utils +public class SharedStringsBasic { + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.build("SharedStringsBasic", "HelloString"); + + String sharedArchiveConfigFile = + TestCommon.getSourceFile("SharedStringsBasic.txt").toString(); + + ProcessBuilder dumpPb = ProcessTools.createJavaProcessBuilder(true, + "-XX:+UseAppCDS", + "-XX:+UseCompressedOops", + "-XX:+UseG1GC", + "-cp", appJar, + "-XX:SharedArchiveConfigFile=" + sharedArchiveConfigFile, + "-XX:SharedArchiveFile=./SharedStringsBasic.jsa", + "-Xshare:dump", + "-Xlog:cds,cds+hashtables"); + + TestCommon.executeAndLog(dumpPb, "dump") + .shouldContain("Shared string table stats") + .shouldHaveExitValue(0); + + ProcessBuilder runPb = ProcessTools.createJavaProcessBuilder(true, + "-XX:+UseAppCDS", + "-XX:+UseCompressedOops", + "-XX:+UseG1GC", + "-cp", appJar, + "-XX:SharedArchiveFile=./SharedStringsBasic.jsa", + "-Xshare:auto", + "-showversion", + "HelloString"); + + TestCommon.executeAndLog(runPb, "run").shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.txt new file mode 100644 index 00000000000..a43dabaaea9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.txt @@ -0,0 +1,60 @@ +VERSION: 1.0 +@SECTION: String +0: +5: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +1: * +1: - +1: . +1: / +1: : +1: C +1: I +1: J +1: U +1: Z +1: _ +8: segments +1: | +5: cp850 +5: cp852 +5: cp855 +5: cp857 +5: cp858 +5: cp862 +5: cp866 +11: ISO_8859_13 +11: ISO_8859_15 +5: cp874 +47: java.lang.invoke.MethodHandle.TRACE_INTERPRETER +7: CHECKED +3: zip +10: waitStatus +33: java.lang.invoke.MethodHandleImpl +7: .jimage +5: cp912 +5: cp914 +5: cp915 +5: cp920 +5: cp923 +5: cp936 +5: euccn +5: eucjp +11: permissions +5: euckr +6: SIGNAL +5: cp737 +17: java.library.path +5: cp775 +13: classValueMap +4: utf8 +9: PROPAGATE +9: baseCount +7: cskoi8r +8: cyrillic +@SECTION: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasicPlus.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasicPlus.java new file mode 100644 index 00000000000..93209142709 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasicPlus.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 2017, 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 Basic plus test for shared strings + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/hotspot/jtreg/runtime/appcds /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build HelloStringPlus sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main SharedStringsBasicPlus + */ + +public class SharedStringsBasicPlus { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJarAndWhiteBox("HelloStringPlus"); + + SharedStringsUtils.dumpWithWhiteBox( TestCommon.list("HelloStringPlus"), + "SharedStringsBasic.txt"); + + SharedStringsUtils.runWithArchiveAndWhiteBox("HelloStringPlus"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsStress.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsStress.java new file mode 100644 index 00000000000..db531617a88 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsStress.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 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 Write a lots of shared strings. + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/hotspot/jtreg/runtime/appcds /test/lib + * @modules jdk.jartool/sun.tools.jar + * @build HelloString + * @run main SharedStringsStress + */ +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class SharedStringsStress { + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.build("SharedStringsStress", "HelloString"); + + String sharedArchiveConfigFile = System.getProperty("user.dir") + File.separator + "SharedStringsStress_gen.txt"; + try (FileOutputStream fos = new FileOutputStream(sharedArchiveConfigFile)) { + PrintWriter out = new PrintWriter(new OutputStreamWriter(fos)); + out.println("VERSION: 1.0"); + out.println("@SECTION: String"); + out.println("31: shared_test_string_unique_14325"); + for (int i=0; i<100000; i++) { + String s = "generated_string " + i; + out.println(s.length() + ": " + s); + } + out.close(); + } + + // Set NewSize to 8m due to dumping could fail in hs-tier6 testing with + // the vm options: -XX:+UnlockCommercialFeatures -XX:+UseDeterministicG1GC + // resulting in vm initialization error: + // "GC triggered before VM initialization completed. Try increasing NewSize, current value 1331K." + OutputAnalyzer dumpOutput = TestCommon.dump(appJar, TestCommon.list("HelloString"), "-XX:NewSize=8m", + "-XX:SharedArchiveConfigFile=" + sharedArchiveConfigFile); + TestCommon.checkDump(dumpOutput); + OutputAnalyzer execOutput = TestCommon.exec(appJar, "HelloString"); + TestCommon.checkExec(execOutput); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsUtils.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsUtils.java new file mode 100644 index 00000000000..5121ae5924e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsUtils.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; + +// A helper/utility class for testing shared strings +public class SharedStringsUtils { + public static final String TEST_JAR_NAME = "test"; + public static final String TEST_JAR_NAME_FULL = "test.jar"; + public static final String WHITEBOX_JAR_NAME = "whitebox"; + + public static String getWbParam() { + return "-Xbootclasspath/a:" + TestCommon.getTestJar(WHITEBOX_JAR_NAME + ".jar"); + } + + // build the test jar + public static void buildJar(String... classes) throws Exception { + JarBuilder.build(TEST_JAR_NAME, classes); + } + + // build the test jar and a whitebox jar + public static void buildJarAndWhiteBox(String... classes) throws Exception { + JarBuilder.build(true, WHITEBOX_JAR_NAME, "sun/hotspot/WhiteBox"); + buildJar(classes); + } + + // execute the "dump" operation, but do not check the output + public static OutputAnalyzer dumpWithoutChecks(String appClasses[], + String sharedDataFile, String... extraOptions) throws Exception { + + String appJar = TestCommon.getTestJar(TEST_JAR_NAME_FULL); + String[] args = + TestCommon.concat(extraOptions, "-XX:+UseCompressedOops", "-XX:+UseG1GC", + "-XX:SharedArchiveConfigFile=" + + TestCommon.getSourceFile(sharedDataFile)); + + return TestCommon.dump(appJar, appClasses, args); + } + + // execute the dump operation and check the output + public static OutputAnalyzer dump(String appClasses[], + String sharedDataFile, String... extraOptions) throws Exception { + OutputAnalyzer output = dumpWithoutChecks(appClasses, sharedDataFile, extraOptions); + checkDump(output); + return output; + } + + public static OutputAnalyzer dumpWithWhiteBox(String appClasses[], + String sharedDataFile, String... extraOptions) throws Exception { + return dump(appClasses, sharedDataFile, + TestCommon.concat(extraOptions, getWbParam()) ); + } + + // execute/run test with shared archive + public static OutputAnalyzer runWithArchiveAuto(String className, + String... extraOptions) throws Exception { + + String appJar = TestCommon.getTestJar(TEST_JAR_NAME_FULL); + String[] args = TestCommon.concat(extraOptions, + "-cp", appJar, "-XX:+UseCompressedOops", "-XX:+UseG1GC", className); + + OutputAnalyzer output = TestCommon.execAuto(args); + checkExecAuto(output); + return output; + } + + public static OutputAnalyzer runWithArchive(String className, + String... extraOptions) throws Exception { + + return runWithArchive(new String[0], className, extraOptions); + } + + public static OutputAnalyzer runWithArchive(String[] extraMatches, + String className, String... extraOptions) throws Exception { + + String appJar = TestCommon.getTestJar(TEST_JAR_NAME_FULL); + String[] args = TestCommon.concat(extraOptions, + "-XX:+UseCompressedOops", "-XX:+UseG1GC", className); + + OutputAnalyzer output = TestCommon.exec(appJar, args); + checkExec(output, extraMatches); + return output; + } + + + // execute/run test with shared archive and white box + public static OutputAnalyzer runWithArchiveAndWhiteBox(String className, + String... extraOptions) throws Exception { + + return runWithArchive(className, + TestCommon.concat(extraOptions, getWbParam(), + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI") ); + } + + public static OutputAnalyzer runWithArchiveAndWhiteBox(String[] extraMatches, + String className, String... extraOptions) throws Exception { + + return runWithArchive(extraMatches, className, + TestCommon.concat(extraOptions, getWbParam(), + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI") ); + } + + + public static void checkDump(OutputAnalyzer output) throws Exception { + output.shouldContain("Shared string table stats"); + TestCommon.checkDump(output); + } + + public static void checkExec(OutputAnalyzer output) throws Exception { + TestCommon.checkExec(output, new String[0]); + } + + public static void checkExecAuto(OutputAnalyzer output) throws Exception { + CDSOptions opts = (new CDSOptions()).setXShareMode("auto"); + TestCommon.checkExec(output, opts); + } + + public static void checkExec(OutputAnalyzer output, String[] extraMatches) throws Exception { + TestCommon.checkExec(output, extraMatches); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsWb.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsWb.java new file mode 100644 index 00000000000..3bd8eeb6152 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsWb.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class SharedStringsWb { + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + String s = "shared_test_string_unique_14325"; + s = s.intern(); + if (wb.areSharedStringsIgnored() || wb.isShared(s)) { + System.out.println("Found shared string."); + } else { + throw new RuntimeException("String is not shared."); + } + } +} + + diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsWbTest.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsWbTest.java new file mode 100644 index 00000000000..fe3f05350a7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsWbTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, 2017, 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 White box test for shared strings + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox SharedStringsWb + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main SharedStringsWbTest + */ + +import java.io.*; +import sun.hotspot.WhiteBox; + +public class SharedStringsWbTest { + public static void main(String[] args) throws Exception { + SharedStringsUtils.buildJarAndWhiteBox("SharedStringsWb"); + + SharedStringsUtils.dumpWithWhiteBox(TestCommon.list("SharedStringsWb"), + "SharedStringsBasic.txt"); + + SharedStringsUtils.runWithArchiveAndWhiteBox("SharedStringsWb"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java new file mode 100644 index 00000000000..c96a75da7e1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, 2017, 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 Regression test for JDK-8098821 + * @bug 8098821 + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires vm.gc.G1 + * @library /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * @modules java.management + * @run main SysDictCrash + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class SysDictCrash { + public static void main(String[] args) throws Exception { + // SharedBaseAddress=0 puts the archive at a very high address on solaris, + // which provokes the crash. + ProcessBuilder dumpPb = ProcessTools.createJavaProcessBuilder(true, + "-XX:+UseG1GC", "-XX:MaxRAMPercentage=12.5", + "-XX:+UseAppCDS", + "-cp", ".", + "-XX:SharedBaseAddress=0", "-XX:SharedArchiveFile=./SysDictCrash.jsa", + "-Xshare:dump", + "-showversion", "-Xlog:cds,cds+hashtables"); + + TestCommon.checkDump(TestCommon.executeAndLog(dumpPb, "dump")); + + ProcessBuilder runPb = ProcessTools.createJavaProcessBuilder(true, + "-XX:+UseG1GC", "-XX:MaxRAMPercentage=12.5", + "-XX:+UseAppCDS", + "-XX:SharedArchiveFile=./SysDictCrash.jsa", + "-Xshare:on", + "-version"); + + TestCommon.checkExec(TestCommon.executeAndLog(runPb, "exec")); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/CorruptDataLine.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/CorruptDataLine.txt new file mode 100644 index 00000000000..fe5fb328c1e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/CorruptDataLine.txt @@ -0,0 +1,60 @@ +VERSION: 1.0 +SECTION: String +0: +5: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +1: * +1: - +1: . +1: / +1: : +1: C +1: I +1: J +1: U +1: Z +1: _ +8: segments +1: | +5: cp850 +5: cp852 +5: cp855 +5: cp857 +5: cp858 +5: cp862 +5: cp866 +11: ISO_8859_13 +11: ISO_8859_15 +5: cp874 +47: java.lang.invoke.MethodHandle.TRACE_INTERPRETER +7: CHECKED +3: zip +10: waitStatus +33: java.lang.invoke.MethodHandleImpl +7: .jimage +5: cp912 +5: cp914 +5: cp915 +5: cp920 +5: cp923 +5: cp936 +5: euccn +5: eucjp +11: permissions +5: euckr +6: SIGNAL +5: cp737 +17: java.library.path +5: cp775 +13: classValueMap +4: utf8 +9: PROPAGATE +9: baseCount +7: cskoi8r +8: cyrillic +#DATATYPE: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidDataType.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidDataType.txt new file mode 100644 index 00000000000..d19db9e4999 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidDataType.txt @@ -0,0 +1,60 @@ +VERSION: 1.0 +@SECTION: String +0: +5: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +1: * +1: - +1: . +1: / +1: : +1: C +1: I +1: J +1: U +1: Z +1: _ +8: segments +1: | +5: cp850 +5: cp852 +5: cp855 +5: cp857 +5: cp858 +5: cp862 +5: cp866 +11: ISO_8859_13 +11: ISO_8859_15 +5: cp874 +47: java.lang.invoke.MethodHandle.TRACE_INTERPRETER +7: CHECKED +3: zip +10: waitStatus +33: java.lang.invoke.MethodHandleImpl +7: .jimage +5: cp912 +5: cp914 +5: cp915 +5: cp920 +5: cp923 +5: cp936 +5: euccn +5: eucjp +11: permissions +5: euckr +6: SIGNAL +5: cp737 +17: java.library.path +5: cp775 +13: classValueMap +4: utf8 +9: PROPAGATE +9: baseCount +7: cskoi8r +8: cyrillic +#DATATYPE: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidHeader.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidHeader.txt new file mode 100644 index 00000000000..02ff35b7246 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidHeader.txt @@ -0,0 +1,60 @@ +Garbage Header x0935#%0sl +@SECTION: String +0: +5: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +1: * +1: - +1: . +1: / +1: : +1: C +1: I +1: J +1: U +1: Z +1: _ +8: segments +1: | +5: cp850 +5: cp852 +5: cp855 +5: cp857 +5: cp858 +5: cp862 +5: cp866 +11: ISO_8859_13 +11: ISO_8859_15 +5: cp874 +47: java.lang.invoke.MethodHandle.TRACE_INTERPRETER +7: CHECKED +3: zip +10: waitStatus +33: java.lang.invoke.MethodHandleImpl +7: .jimage +5: cp912 +5: cp914 +5: cp915 +5: cp920 +5: cp923 +5: cp936 +5: euccn +5: eucjp +11: permissions +5: euckr +6: SIGNAL +5: cp737 +17: java.library.path +5: cp775 +13: classValueMap +4: utf8 +9: PROPAGATE +9: baseCount +7: cskoi8r +8: cyrillic +#DATATYPE: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidString.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidString.txt new file mode 100644 index 00000000000..104785cc934 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidString.txt @@ -0,0 +1,6 @@ +VERSION: 1.0 +@SECTION: String +31: shred_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 + diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidStringFormat.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidStringFormat.txt new file mode 100644 index 00000000000..bf4fe475ad7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidStringFormat.txt @@ -0,0 +1,60 @@ +VERSION: 1.0 +@SECTION: String +0: +5:: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +1: * +1: - +1: . +1: / +1: : +1: C +1: I +1: J +1: U +1: Z +1: _ +8: segments +1: | +5: cp850 +5: cp852 +5: cp855 +5: cp857 +5: cp858 +5: cp862 +5: cp866 +11: ISO_8859_13 +11: ISO_8859_15 +5: cp874 +47: java.lang.invoke.MethodHandle.TRACE_INTERPRETER +7: CHECKED +3: zip +10: waitStatus +33: java.lang.invoke.MethodHandleImpl +7: .jimage +5: cp912 +5: cp914 +5: cp915 +5: cp920 +5: cp923 +5: cp936 +5: euccn +5: eucjp +11: permissions +5: euckr +6: SIGNAL +5: cp737 +17: java.library.path +5: cp775 +13: classValueMap +4: utf8 +9: PROPAGATE +9: baseCount +7: cskoi8r +8: cyrillic +#DATATYPE: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidSymbol.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidSymbol.txt new file mode 100644 index 00000000000..7da06b825eb --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidSymbol.txt @@ -0,0 +1,12 @@ +VERSION: 1.0 +@SECTION: String +0: +5: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +8: cyrillic +@SECTION: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMet%%%hod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidSymbolFormat.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidSymbolFormat.txt new file mode 100644 index 00000000000..affa466d4e9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidSymbolFormat.txt @@ -0,0 +1,11 @@ +VERSION: 1.0 +@SECTION: String +0: +5: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +@SECTION: Symbol +41: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidVersion.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidVersion.txt new file mode 100644 index 00000000000..2d917344c6e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/InvalidVersion.txt @@ -0,0 +1,60 @@ +VERSION: 0.0 +@SECTION: String +0: +5: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +1: * +1: - +1: . +1: / +1: : +1: C +1: I +1: J +1: U +1: Z +1: _ +8: segments +1: | +5: cp850 +5: cp852 +5: cp855 +5: cp857 +5: cp858 +5: cp862 +5: cp866 +11: ISO_8859_13 +11: ISO_8859_15 +5: cp874 +47: java.lang.invoke.MethodHandle.TRACE_INTERPRETER +7: CHECKED +3: zip +10: waitStatus +33: java.lang.invoke.MethodHandleImpl +7: .jimage +5: cp912 +5: cp914 +5: cp915 +5: cp920 +5: cp923 +5: cp936 +5: euccn +5: eucjp +11: permissions +5: euckr +6: SIGNAL +5: cp737 +17: java.library.path +5: cp775 +13: classValueMap +4: utf8 +9: PROPAGATE +9: baseCount +7: cskoi8r +8: cyrillic +#DATATYPE: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/OverflowPrefix.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/OverflowPrefix.txt new file mode 100644 index 00000000000..8da872dca23 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/OverflowPrefix.txt @@ -0,0 +1,11 @@ +VERSION: 1.0 +@SECTION: String +0: +2147483648: cp819 +31: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +@SECTION: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/TruncatedString.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/TruncatedString.txt new file mode 100644 index 00000000000..849f8b5ddfd --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/TruncatedString.txt @@ -0,0 +1,10 @@ +VERSION: 1.0 +@SECTION: String +2147483647: s +5: cp819 +31: shared_test_string_intern_12345 +7: test123 +@SECTION: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/UnrecognizedPrefix.txt b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/UnrecognizedPrefix.txt new file mode 100644 index 00000000000..e979c3d8910 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/invalidFormat/UnrecognizedPrefix.txt @@ -0,0 +1,11 @@ +VERSION: 1.0 +@SECTION: String +0: +5: cp819 +3E: shared_test_string_unique_14325 +31: shared_test_string_intern_12345 +7: test123 +@SECTION: Symbol +41 -1: (Ljava/util/Set;Ljava/lang/Object;)V +10 -1: linkMethod +20 -1: isAlphaNumericString diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/ArrayListTest.java b/test/hotspot/jtreg/runtime/appcds/test-classes/ArrayListTest.java new file mode 100644 index 00000000000..d6ac26e960a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/ArrayListTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.util.*; + +// This is a test case executed by DumpClassList.java to load classes +// from various places to ensure that they are not written to the class list. +public class ArrayListTest { + public static void main(String args[]) throws Exception { + // The following lambda usage should generate various classes like + // java.lang.invoke.LambdaForm$MH/1146743572. All of them should be excluded from + // the class list. + List a = new ArrayList<>(); + a.add("hello world."); + a.forEach(str -> System.out.println(str)); + + System.out.println(Class.forName("java.lang.NewClass")); // should be excluded from the class list. + System.out.println(Class.forName("boot.append.Foo")); // should be excluded from the class list. + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/BootClassPathAppendHelper.java b/test/hotspot/jtreg/runtime/appcds/test-classes/BootClassPathAppendHelper.java new file mode 100644 index 00000000000..79cd2805ee3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/BootClassPathAppendHelper.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class BootClassPathAppendHelper { + public static void main(String[] args) throws ClassNotFoundException { + Class cls = Class.forName("Hello"); + + if (cls == null) { + throw new java.lang.RuntimeException("Cannot find Hello.class"); + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (!wb.isSharedClass(cls)) { + System.out.println("Hello.class is not in shared space as expected."); + } else { + throw new java.lang.RuntimeException("Hello.class shouldn't be in shared space."); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/C1.java b/test/hotspot/jtreg/runtime/appcds/test-classes/C1.java new file mode 100644 index 00000000000..86201cd4e34 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/C1.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, 2017, 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 sealed.pkg; + +public class C1 { +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/C2.java b/test/hotspot/jtreg/runtime/appcds/test-classes/C2.java new file mode 100644 index 00000000000..ad0026fbc53 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/C2.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, 2017, 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 pkg; + +public class C2 { +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/CheckIfShared.java b/test/hotspot/jtreg/runtime/appcds/test-classes/CheckIfShared.java new file mode 100644 index 00000000000..6e919ad5bce --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/CheckIfShared.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class CheckIfShared { + public static void main(String args[]) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + if ("true".equals(args[0])) { + if (!wb.isSharedClass(CheckIfShared.class)) { + throw new RuntimeException("wb.isSharedClass(CheckIfShared.class) should be true"); + } + } else { + if (wb.isSharedClass(CheckIfShared.class)) { + throw new RuntimeException("wb.isSharedClass(CheckIfShared.class) should be false"); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/Child.java b/test/hotspot/jtreg/runtime/appcds/test-classes/Child.java new file mode 100644 index 00000000000..8a3684e15a6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/Child.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +public class Child extends Super {} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr1.java b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr1.java new file mode 100644 index 00000000000..5006870cd6d --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr1.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class CpAttr1 { + public static void main(String args[]) { + System.out.println("2"); CpAttr2.doit(); // Only the version of this class defined in CpAttr2.java will not throw exception. + System.out.println("3"); CpAttr3.doit(); // Only the version of this class defined in CpAttr3.java will not throw exception. + System.out.println("4"); CpAttr4.doit(); // Only the version of this class defined in CpAttr4.java will not throw exception. + System.out.println("5"); CpAttr5.doit(); // Only the version of this class defined in CpAttr5.java will not throw exception. + System.out.println("Test passed"); + } +} + +class CpAttr2 { static void doit() {throw new RuntimeException("");} } +class CpAttr3 { static void doit() {throw new RuntimeException("");} } +class CpAttr4 { static void doit() {throw new RuntimeException("");} } +class CpAttr5 { static void doit() {throw new RuntimeException("");} } diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr2.java b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr2.java new file mode 100644 index 00000000000..4777e1caf9e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr2.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +class CpAttr2 { static void doit() {} } diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr3.java b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr3.java new file mode 100644 index 00000000000..96b19d0424c --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr3.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +class CpAttr2 { static void doit() {throw new RuntimeException("");} } +class CpAttr3 { static void doit() {} } diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr4.java b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr4.java new file mode 100644 index 00000000000..9711148f877 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr4.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +class CpAttr2 { static void doit() {throw new RuntimeException("");} } +class CpAttr3 { static void doit() {throw new RuntimeException("");} } +class CpAttr4 { static void doit() {} } +class CpAttr5 { static void doit() {throw new RuntimeException("");} } diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr5.java b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr5.java new file mode 100644 index 00000000000..94812653c48 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/CpAttr5.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +class CpAttr5 { static void doit() {} } diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/DummyClassHelper.java b/test/hotspot/jtreg/runtime/appcds/test-classes/DummyClassHelper.java new file mode 100644 index 00000000000..56ffa75bd29 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/DummyClassHelper.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.*; +import java.lang.reflect.*; +import sun.hotspot.WhiteBox; + +public class DummyClassHelper { + public static void main(String[] args) throws Exception { + String[] classNames = {args[0], args[1]}; + Class cls = null; + if (args.length == 2) { + for (int i = 0; i < classNames.length; i++) { + Method m = null; + cls = Class.forName(classNames[i]); + try { + m = cls.getMethod("thisClassIsDummy"); + throw new java.lang.RuntimeException(classNames[i] + + " should be loaded from the jimage and should not have the thisClassIsDummy() method."); + } catch(NoSuchMethodException ex) { + System.out.println(ex.toString()); + } + } + } else { + WhiteBox wb = WhiteBox.getWhiteBox(); + for (int i = 0; i < classNames.length; i++) { + cls = Class.forName(classNames[i]); + if (!wb.isSharedClass(cls)) { + System.out.println(classNames[i] + ".class" + " is not in shared space as expected."); + } else { + throw new java.lang.RuntimeException(classNames[i] + + ".class shouldn't be in shared space."); + } + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/EmptyClassHelper.java b/test/hotspot/jtreg/runtime/appcds/test-classes/EmptyClassHelper.java new file mode 100644 index 00000000000..86805214617 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/EmptyClassHelper.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.*; +import java.lang.reflect.*; +import jdk.internal.misc.JavaLangAccess; +import jdk.internal.misc.SharedSecrets; + +class EmptyClassHelper { + static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + static final String USE_APP = "useAppLoader"; + public static void main(String[] args) throws Exception { + Class cls = null; + Method m = null; + ClassLoader appLoader = ClassLoader.getSystemClassLoader(); + String className = "com.sun.tools.javac.Main"; + if (args[0].equals(USE_APP)) { + cls = appLoader.loadClass(className); + System.out.println("appLoader loaded class"); + try { + m = cls.getMethod("main", String[].class); + System.out.println("appLoader found method main"); + } catch(NoSuchMethodException ex) { + System.out.println(ex.toString()); + } + } else { + cls = jla.findBootstrapClassOrNull(appLoader, className); + System.out.println("bootLoader loaded class"); + System.out.println("cls = " + cls); + try { + m = cls.getMethod("main", String[].class); + System.out.println("bootLoader found method main"); + } catch(NoSuchMethodException ex) { + System.out.println(ex.toString()); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/FieldAnnotationsApp.java b/test/hotspot/jtreg/runtime/appcds/test-classes/FieldAnnotationsApp.java new file mode 100644 index 00000000000..70808d8af64 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/FieldAnnotationsApp.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; + +public class FieldAnnotationsApp { + @MyAnnotation(name="myField1", value="myValue1") + public String myField1 = null; + + @MyAnnotation(name="myField2", value="myValue2") + public String myField2 = null; + + public static void main(String args[]) throws Exception { + for (int i=1; i<=2; i++) { + Field field = FieldAnnotationsApp.class.getField("myField" + i); + Annotation[] annotations = field.getDeclaredAnnotations(); + + for (Annotation anno : annotations){ + if (anno instanceof MyAnnotation){ + MyAnnotation myAnno = (MyAnnotation) anno; + String name = myAnno.name(); + String value = myAnno.value(); + + System.out.println("Field : " + field.getName()); + System.out.println(" myAnno.name : " + name); + System.out.println(" myAnno.value: " + value); + + if (!(name.equals("myField" + i) && value.equals("myValue" + i))) { + throw new Exception("Unexpected annotation values: " + i + " = " + value); + } + } + } + } + System.out.println("Field annotations are OK."); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/ForNameTest.java b/test/hotspot/jtreg/runtime/appcds/test-classes/ForNameTest.java new file mode 100644 index 00000000000..b313af1ccc7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/ForNameTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class ForNameTest { + public static void main(String[] args) throws Throwable { + // Hello is on the bootclasspath. The defining classloader is + // the NULL classloader. See AppCDSClassLoaderTest. + Class c = Class.forName("Hello"); + ClassLoader cl = c.getClassLoader(); + if (cl != null) { + throw new RuntimeException( + "Test Failed. Wrong classloader is used. Expect the NULL classloader."); + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (!wb.isSharedClass(c)) { + System.out.println("As expected, Hello.class is not in shared space."); + } else { + throw new java.lang.RuntimeException("Hello.class shouldn't be in shared space."); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/Greet.java b/test/hotspot/jtreg/runtime/appcds/test-classes/Greet.java new file mode 100644 index 00000000000..174e97ac205 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/Greet.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class Greet { + + public String Greeting() { + return new String(", how are you?"); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIA64.java b/test/hotspot/jtreg/runtime/appcds/test-classes/Hello.java similarity index 73% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIA64.java rename to test/hotspot/jtreg/runtime/appcds/test-classes/Hello.java index a113cbe4447..dc134771ba5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIA64.java +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/Hello.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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,18 +22,8 @@ * */ -package sun.jvm.hotspot.debugger; - -public class MachineDescriptionIA64 extends MachineDescriptionTwosComplement implements MachineDescription { - public long getAddressSize() { - return 8; - } - - public boolean isLP64() { - return true; - } - - public boolean isBigEndian() { - return false; +public class Hello { + public static void main(String args[]) { + System.out.println("Hello World"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExt.java b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExt.java new file mode 100644 index 00000000000..bd11763271a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExt.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class HelloExt { + public static void main(String[] args) throws Throwable { + + String className = "org.omg.CORBA.ORB"; + Class cls = Class.forName(className); + + ClassLoader loader = cls.getClassLoader(); + if (loader != ClassLoader.getPlatformClassLoader()) { + throw new java.lang.RuntimeException(className + " should be load by PlatformClassLoader but it is loaded by " + loader); + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (wb.isSharedClass(cls)) { + System.out.println("As expected, " + className + " is in shared space."); + } else { + throw new java.lang.RuntimeException(className + " is not in shared space."); + } + + className = "[Ljava.lang.Comparable;"; + cls = Class.forName(className); + loader = cls.getClassLoader(); + if (loader != null) { + throw new java.lang.RuntimeException(className + " should be load by the NULL class loader but it is loaded by " + loader); + } + + if (wb.isSharedClass(cls)) { + System.out.println("As expected, " + className + " is in shared space."); + } else { + throw new java.lang.RuntimeException(className + " is not in shared space."); + } + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExtApp.java b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExtApp.java new file mode 100644 index 00000000000..a4dd73f390b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExtApp.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class HelloExtApp { + public static void main(String args[]) { + System.out.println("Hello World Ext: " + HelloExtExt.class.getProtectionDomain()); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExtExt.java b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExtExt.java new file mode 100644 index 00000000000..d74901c782a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExtExt.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class HelloExtExt { + +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/HelloMore.java b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloMore.java new file mode 100644 index 00000000000..dee1b239177 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloMore.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class HelloMore { + public static void main(String args[]) { + Hello.main(args); + System.out.println("Hello World ... More"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/HelloWB.java b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloWB.java new file mode 100644 index 00000000000..92c0d9e02fa --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloWB.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class HelloWB { + public static void main(String[] args) throws Throwable { + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (wb.isSharedClass(HelloWB.class)) { + System.out.println("As expected, HelloWB.class is in shared space."); + } else { + throw new java.lang.RuntimeException("HelloWB.class should be in shared space."); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/Hi.java b/test/hotspot/jtreg/runtime/appcds/test-classes/Hi.java new file mode 100644 index 00000000000..8250c323a8b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/Hi.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class Hi extends Greet { + public static void main(String args[]) { + Greet g = new Greet(); + MyClass.doit(g.Greeting()); + } + public static class MyClass { + public static void doit(String greeting) { + System.out.println("Hi" + greeting); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/Iloadw.jasm b/test/hotspot/jtreg/runtime/appcds/test-classes/Iloadw.jasm new file mode 100644 index 00000000000..90d31f9fbf6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/Iloadw.jasm @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class Iloadw + version 51: 0 +{ + public static Method run:"()I" + stack 1 locals 400 + { + iconst_0; + istore_w 300; + iinc_w 300,1; + iload_w 300; + ireturn; + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/IloadwMain.java b/test/hotspot/jtreg/runtime/appcds/test-classes/IloadwMain.java new file mode 100644 index 00000000000..315e00a2b38 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/IloadwMain.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, 2017, 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. + * + */ + +public class IloadwMain { + public static void main(String args[]) { + int result = Iloadw.run(); + if (result != 1) { + throw new RuntimeException( + "Failed. Result is " + result + ", expect 1."); + } else { + System.out.println("Passed."); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/JimageClassPackage.java b/test/hotspot/jtreg/runtime/appcds/test-classes/JimageClassPackage.java new file mode 100644 index 00000000000..f9358a1e28f --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/JimageClassPackage.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +public class JimageClassPackage { + public static void main(String args[]) throws Throwable { + // Test Package for boot/app/ext module classes from the "modules" jimage. + // The following classes are archived. See runtime/AppCDS/Package.java. + // java.util.Dictionary (testcase 0), + // sun.tools.javac.Main (testcase 1), + // jdk.nio.zipfs.ZipInfo (testcase 2), + // java.net.URL (testcase 3), + // sun.rmi.rmic.Main (testcase 4), + // com.sun.jndi.dns.DnsName (testcase 5) + String testcases[][] = + {{"Loading shared boot module class first", "java.util", + "java.util.Dictionary", "java.util.ServiceConfigurationError"}, + + {"Loading shared app module class first", "sun.tools.javac", + "sun.tools.javac.Main", "sun.tools.javac.BatchParser"}, + + {"Loading shared ext module class first", "jdk.nio.zipfs", + "jdk.nio.zipfs.ZipInfo", "jdk.nio.zipfs.ZipPath"}, + + {"Loading non-shared boot module class first", "java.net", + "java.net.HttpCookie", "java.net.URL"}, + + {"Loading non-shared app module class first", "sun.rmi.rmic", + "sun.rmi.rmic.RMIGenerator", "sun.rmi.rmic.Main"}, + + {"Loading non-shared ext module class first", "com.sun.jndi.dns", + "com.sun.jndi.dns.Resolver", "com.sun.jndi.dns.DnsName"}}; + + JimageClassPackage test = new JimageClassPackage(); + for (int i = 0; i < testcases.length; i++) { + System.out.println("Testcase " + i + ": " + testcases[i][0]); + test.testPackage(testcases[i][1], testcases[i][2], testcases[i][3]); + } + } + + private void testPackage (String pkg, + String shared, + String nonShared) throws Throwable { + Class c1 = Class.forName(shared); + ClassLoader cl = c1.getClassLoader(); + Package pkg_from_loader; + if (cl != null) { + pkg_from_loader = cl.getDefinedPackage(pkg); + } else { + pkg_from_loader = Package.getPackage(pkg); + } + + Package pkg_from_shared_class = c1.getPackage(); + + Class c2 = Class.forName(nonShared); + Package pkg_from_nonshared_class = c2.getPackage(); + + if (pkg_from_loader != null && + pkg_from_shared_class != null && + pkg_from_loader == pkg_from_shared_class && + pkg_from_shared_class == pkg_from_nonshared_class && + pkg_from_shared_class.getName().equals(pkg)) { + System.out.println("Expected package: " + pkg_from_shared_class.toString()); + } else { + System.out.println("Unexpected package" + pkg_from_shared_class); + System.exit(1); + } + if (pkg_from_shared_class.isSealed()) { + System.out.println("Package is sealed"); + } else { + System.out.println("Package is not sealed"); + System.exit(1); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/JimageClassProtDomain.java b/test/hotspot/jtreg/runtime/appcds/test-classes/JimageClassProtDomain.java new file mode 100644 index 00000000000..e47aaaa8a36 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/JimageClassProtDomain.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +public class JimageClassProtDomain { + public static void main(String args[]) throws Throwable { + // Test ProtectionDomain for boot/app/ext module classes from the "modules" jimage. + // The following classes are archived. See runtime/AppCDS/ProtectionDomain.java. + // java.util.Dictionary (testcase 0), + // sun.tools.javac.Main (testcase 1), + // jdk.nio.zipfs.ZipInfo (testcase 2), + // java.net.URL (testcase 3), + // sun.rmi.rmic.Main (testcase 4), + // com.sun.jndi.dns.DnsName (testcase 5) + String testcases[][] = + {{"Loading shared boot module class first", + "java.util.Dictionary", "java.util.ServiceConfigurationError"}, + + {"Loading shared app module class first", + "sun.tools.javac.Main", "sun.tools.javac.BatchParser"}, + + {"Loading shared ext module class first", + "jdk.nio.zipfs.ZipInfo", "jdk.nio.zipfs.ZipPath"}, + + {"Loading non-shared boot module class first", + "java.net.HttpCookie", "java.net.URL"}, + + {"Loading non-shared app module class first", + "sun.rmi.rmic.RMIGenerator", "sun.rmi.rmic.Main"}, + + {"Loading non-shared ext module class first", + "com.sun.jndi.dns.Resolver", "com.sun.jndi.dns.DnsName"}}; + for (int i = 0; i < testcases.length; i++) { + System.out.println("Testcase " + i + ": " + testcases[i][0]); + JimageClassProtDomain.testProtectionDomain(testcases[i][1], testcases[i][2]); + } + } + + private static void testProtectionDomain(String shared, String nonShared) + throws Throwable { + Class c1 = Class.forName(shared); + Class c2 = Class.forName(nonShared); + if (c1.getProtectionDomain() != c2.getProtectionDomain()) { + System.out.println("Failed: Protection Domains do not match!"); + System.out.println(c1.getProtectionDomain()); + System.out.println(c1.getProtectionDomain().getCodeSource()); + System.out.println(c2.getProtectionDomain()); + System.out.println(c2.getProtectionDomain().getCodeSource()); + System.exit(1); + } else { + System.out.println("Passed: Protection Domains match."); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java b/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java new file mode 100644 index 00000000000..e0c0ea55fb6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +public class JvmtiApp { + static Class forname() { + try { + return Class.forName("Hello"); + } catch (Throwable t) { + return null; + } + } + + static void failed(String msg) { + System.out.println("TEST FAILED: " + msg); + System.exit(1); + } + + // See ../JvmtiAddPath.java for how the classpaths are configured. + public static void main(String args[]) { + if (args[0].equals("noadd")) { + if (forname() != null) { + failed("Hello class was loaded unexpectedly"); + } + // We use -verbose:class to verify that Extra.class IS loaded by AppCDS if + // the boot classpath HAS NOT been appended. + ExtraClass.doit(); + System.exit(0); + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + + if (args[0].equals("bootonly")) { + wb.addToBootstrapClassLoaderSearch(args[1]); + Class cls = forname(); + if (cls == null) { + failed("Cannot find Hello class"); + } + if (cls.getClassLoader() != null) { + failed("Hello class not loaded by boot classloader"); + } + } else if (args[0].equals("apponly")) { + wb.addToSystemClassLoaderSearch(args[1]); + Class cls = forname(); + if (cls == null) { + failed("Cannot find Hello class"); + } + if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) { + failed("Hello class not loaded by app classloader"); + } + } else if (args[0].equals("noadd-appcds")) { + Class cls = forname(); + if (cls == null) { + failed("Cannot find Hello class"); + } + if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) { + failed("Hello class not loaded by app classloader"); + } + } else if (args[0].equals("appandboot")) { + wb.addToBootstrapClassLoaderSearch(args[1]); + wb.addToSystemClassLoaderSearch(args[2]); + Class cls = forname(); + if (cls == null) { + failed("Cannot find Hello class"); + } + if (cls.getClassLoader() != null) { + failed("Hello class not loaded by boot classloader"); + } + } else { + failed("unknown option " + args[0]); + } + + // We use -verbose:class to verify that Extra.class IS NOT loaded by AppCDS if + // the boot classpath HAS been appended. + ExtraClass.doit(); + + System.out.println("Test passed: " + args[0]); + } +} + +class ExtraClass { + static void doit() {} +} \ No newline at end of file diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/MethodNoReturn.jasm b/test/hotspot/jtreg/runtime/appcds/test-classes/MethodNoReturn.jasm new file mode 100644 index 00000000000..c9c17a50473 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/MethodNoReturn.jasm @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017, 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. + * + */ + +/* +WAS: + +class MethodNoReturn { + void badMethod() {} +} +*/ + +super class MethodNoReturn + version 52:0 +{ + + +Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +Method badMethod:"()V" + stack 0 locals 1 +{ + /* + should be: + return; + */ + + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + pop; + iconst_1; + iconst_1; + iconst_1; + iconst_1; + iconst_1; + iconst_1; + iconst_1; + iconst_1; + pop; + pop; + pop; + pop; + pop; + pop; + pop; + pop; + // no return here -- so this class will fail verification +} + +} // end Class MethodNoReturn diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/MissingSuper.java b/test/hotspot/jtreg/runtime/appcds/test-classes/MissingSuper.java new file mode 100644 index 00000000000..ef47a7cb9e4 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/MissingSuper.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class MissingSuper { + public static void main(String args[]) { + try { + new MissingSuperSub(); + } catch (NoClassDefFoundError e) { + System.out.println("Expected NoClassDefFoundError:"); + e.printStackTrace(System.out); + } + + try { + new MissingSuperImpl(); + } catch (NoClassDefFoundError e) { + System.out.println("Expected NoClassDefFoundError:"); + e.printStackTrace(System.out); + } + } +} + +class MissingSuperSup {} // This class will be deleted from missing_super.jar before dumping + +class MissingSuperSub extends MissingSuperSup {} + +interface MissingSuperIntf {} // This interface will be deleted from missing_super.jar before dumping + +class MissingSuperImpl implements MissingSuperIntf {} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/MultiProcClass.java b/test/hotspot/jtreg/runtime/appcds/test-classes/MultiProcClass.java new file mode 100644 index 00000000000..cf67318a24e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/MultiProcClass.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import sun.hotspot.WhiteBox; + +// This class should be loaded from a shared archive. +public class MultiProcClass { + private static String instanceLabel; + + public static void main(String args[]) throws Exception { + instanceLabel = args[0]; + String checkPmap = args[1]; + + long pid = ProcessHandle.current().pid(); + System.out.println(inst("========================== Starting MultiProcClass")); + System.out.println(inst("My PID: " + pid )); + System.out.println(inst("checkPmap = <" + checkPmap + ">" )); + + if ("true".equals(checkPmap)) { + if (runPmap(pid, true) != 0) + System.out.println("MultiProcClass: Pmap failed"); + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + if (!wb.isSharedClass(MultiProcClass.class)) { + throw new RuntimeException(inst("MultiProcClass should be shared but is not.")); + } + + System.out.println(inst("========================== Leaving MultiProcClass")); + } + + // A convenience method to append process instance label + private static String inst(String msg) { + return "process-" + instanceLabel + " : " + msg; + } + + // Use on Linux-only; requires jdk-9 for Process.pid() + public static int runPmap(long pid, boolean inheritIO) throws Exception { + ProcessBuilder pmapPb = new ProcessBuilder("pmap", "" + pid); + if (inheritIO) + pmapPb.inheritIO(); + + return pmapPb.start().waitFor(); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64ThreadContext.java b/test/hotspot/jtreg/runtime/appcds/test-classes/MyAnnotation.java similarity index 60% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64ThreadContext.java rename to test/hotspot/jtreg/runtime/appcds/test-classes/MyAnnotation.java index ba739808002..cbec72aecf6 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/ia64/WindbgIA64ThreadContext.java +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/MyAnnotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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,25 +22,15 @@ * */ -package sun.jvm.hotspot.debugger.windbg.ia64; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.ia64.*; -import sun.jvm.hotspot.debugger.windbg.*; +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) -class WindbgIA64ThreadContext extends IA64ThreadContext { - private WindbgDebugger debugger; - - public WindbgIA64ThreadContext(WindbgDebugger debugger) { - super(); - this.debugger = debugger; - } - - public void setRegisterAsAddress(int index, Address value) { - setRegister(index, debugger.getAddressValue(value)); - } - - public Address getRegisterAsAddress(int index) { - return debugger.newAddress(getRegister(index)); - } +public @interface MyAnnotation { + public String name(); + public String value(); } diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/PackageSealingTest.java b/test/hotspot/jtreg/runtime/appcds/test-classes/PackageSealingTest.java new file mode 100644 index 00000000000..a1e8ea0a234 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/PackageSealingTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.Package; + +public class PackageSealingTest { + public static void main(String args[]) { + try { + Class c1 = PackageSealingTest.class.forName("sealed.pkg.C1"); + Class c2 = PackageSealingTest.class.forName("pkg.C2"); + Package p1 = c1.getPackage(); + System.out.println("Package 1: " + p1.toString()); + Package p2 = c2.getPackage(); + System.out.println("Package 2: " + p2.toString()); + + if (!p1.isSealed()) { + System.out.println("Failed: sealed.pkg is not sealed."); + System.exit(0); + } + + if (p2.isSealed()) { + System.out.println("Failed: pkg is sealed."); + System.exit(0); + } + + System.out.println("OK"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/PackageTest.java b/test/hotspot/jtreg/runtime/appcds/test-classes/PackageTest.java new file mode 100644 index 00000000000..f5f1f15014b --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/PackageTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, 2017, 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 p; + +public class PackageTest { + public static void main(String args[]) { + (new PackageTest()).test(); + } + + private void test() { + ClassLoader cl = PackageTest.class.getClassLoader(); + Package pkg_from_loader; + if (cl != null) { + pkg_from_loader = cl.getDefinedPackage("p"); + } else { + pkg_from_loader = Package.getPackage("p"); + } + + Package pkg = PackageTest.class.getPackage(); + if (pkg_from_loader != null && pkg == pkg_from_loader && + pkg.getName().equals("p")) { + System.out.println("Expected package: " + pkg); + } else { + System.out.println("Unexpected package: " + pkg); + System.exit(1); + } + if (pkg.isSealed()) { + System.out.println("Package is sealed"); + System.exit(1); + } else { + System.out.println("Package is not sealed"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/ParallelClasses.java b/test/hotspot/jtreg/runtime/appcds/test-classes/ParallelClasses.java new file mode 100644 index 00000000000..a4d0520f235 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/ParallelClasses.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, 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. + * + */ + +class ParallelClass0 {} +class ParallelClass1 {} +class ParallelClass2 {} +class ParallelClass3 {} +class ParallelClass4 {} +class ParallelClass5 {} +class ParallelClass6 {} +class ParallelClass7 {} +class ParallelClass8 {} +class ParallelClass9 {} +class ParallelClass10 {} +class ParallelClass11 {} +class ParallelClass12 {} +class ParallelClass13 {} +class ParallelClass14 {} +class ParallelClass15 {} +class ParallelClass16 {} +class ParallelClass17 {} +class ParallelClass18 {} +class ParallelClass19 {} +class ParallelClass20 {} +class ParallelClass21 {} +class ParallelClass22 {} +class ParallelClass23 {} +class ParallelClass24 {} +class ParallelClass25 {} +class ParallelClass26 {} +class ParallelClass27 {} +class ParallelClass28 {} +class ParallelClass29 {} +class ParallelClass30 {} +class ParallelClass31 {} +class ParallelClass32 {} +class ParallelClass33 {} +class ParallelClass34 {} +class ParallelClass35 {} +class ParallelClass36 {} +class ParallelClass37 {} +class ParallelClass38 {} +class ParallelClass39 {} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/ParallelLoad.java b/test/hotspot/jtreg/runtime/appcds/test-classes/ParallelLoad.java new file mode 100644 index 00000000000..d47c3343845 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/ParallelLoad.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.*; +import java.net.*; +import java.lang.reflect.Field; + + +// This test helper is parameterized by: +// - class transformation mode: property "appcds.parallel.transform.mode" +// - class loader test types +// +// In the case of transformMode == "cflh", the transformation is performed +// by AppCDS/jvmti/TransformerAgent.java. The classes to be transformed, such as +// ParallelClassTr0, are defined in ./jvmti/parallelLoad/ParallelClasses.java + +public class ParallelLoad { + public static int MAX_CLASSES = 40; + public static int NUM_THREADS = 4; + + public final static int SYSTEM_LOADER = 0; + public final static int SINGLE_CUSTOM_LOADER = 1; + public final static int MULTI_CUSTOM_LOADER = 2; + + public static final int FINGERPRINT_MODE = 1; + public static final int API_MODE = 2; + + public static int loaderType = SYSTEM_LOADER; + public static ClassLoader classLoaders[]; + public static int mode = FINGERPRINT_MODE; + + public static float timeoutFactor = + Float.parseFloat(System.getProperty("test.timeout.factor", "1.0")); + + public static void main(String args[]) throws Throwable { + run(args, null); + } + public static void run(String args[], ClassLoader loaders[]) throws Throwable { + String customJar = null; + System.out.println("ParallelLoad: timeoutFactor = " + timeoutFactor); + + if (args.length >= 1) { + if ("SINGLE_CUSTOM_LOADER".equals(args[0])) { + loaderType = SINGLE_CUSTOM_LOADER; + customJar = args[2]; + } else if ("MULTI_CUSTOM_LOADER".equals(args[0])) { + loaderType = MULTI_CUSTOM_LOADER; + customJar = args[2]; + } else if ("SYSTEM_LOADER".equals(args[0])) { + loaderType = SYSTEM_LOADER; + } else { + throw new RuntimeException("Unexpected loaderType" + args[0]); + } + } + + if (customJar != null) { + if ("FINGERPRINT_MODE".equals(args[1])) { + mode = FINGERPRINT_MODE; + classLoaders = new ClassLoader[NUM_THREADS]; + for (int i=0; i loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + called = true; + System.out.println("TestClassLoader: loadClass(\"" + name + "\", " + resolve + ")"); + return (super.loadClass(name, resolve)); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/TrySwitchMyLoader.java b/test/hotspot/jtreg/runtime/appcds/test-classes/TrySwitchMyLoader.java new file mode 100644 index 00000000000..48a455debd0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/TrySwitchMyLoader.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class TrySwitchMyLoader { + public static void main(String args[]) { + System.out.println("TrySwitchMyLoader's loader = " + ReportMyLoader.class.getClassLoader()); + System.setProperty("java.system.class.loader", "TestClassLoader"); + + // This should still report the same loader as TrySwitchMyLoader.class.getClassLoader(), + // as setting the java.system.class.loader after main method has been executed + // has no effect. + ReportMyLoader.main(args); + } +} + diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/Util.java b/test/hotspot/jtreg/runtime/appcds/test-classes/Util.java new file mode 100644 index 00000000000..4289c765257 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/Util.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.*; +import java.lang.reflect.*; +import java.util.jar.*; + +public class Util { + /** + * Invoke the loader.defineClass() class method to define the class stored in clsFile, + * with the following modification: + *
      + *
    • All ASCII strings in the class file bytes that matches fromString will be replaced with toString. + * NOTE: the two strings must be the exact same length. + *
    + */ + public static Class defineModifiedClass(ClassLoader loader, File clsFile, String fromString, String toString) + throws FileNotFoundException, IOException, NoSuchMethodException, IllegalAccessException, + InvocationTargetException + { + DataInputStream dis = new DataInputStream(new FileInputStream(clsFile)); + byte[] buff = new byte[(int)clsFile.length()]; + dis.readFully(buff); + replace(buff, fromString, toString); + + System.out.println("Loading from: " + clsFile + " (" + buff.length + " bytes)"); + + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", + buff.getClass(), int.class, int.class); + defineClass.setAccessible(true); + + // We directly call into ClassLoader.defineClass() to define the "Super" class. Also, + // rewrite its classfile so that it returns ___yyy___ instead of ___xxx___. Changing the + // classfile will guarantee that this class will NOT be loaded from the CDS archive. + Class cls = (Class)defineClass.invoke(loader, buff, new Integer(0), new Integer(buff.length)); + System.out.println("Loaded : " + cls); + + return cls; + } + + /** + * @return the number of occurrences of the from string that + * have been replaced. + */ + public static int replace(byte buff[], String from, String to) { + if (to.length() != from.length()) { + throw new RuntimeException("bad strings"); + } + byte f[] = asciibytes(from); + byte t[] = asciibytes(to); + byte f0 = f[0]; + + int numReplaced = 0; + int max = buff.length - f.length; + for (int i=0; i cpuSet = CPUSetsReader.parseCpuSet(cpuSetStr); + + // Test subset of cpuset with one element + if (cpuSet.size() >= 1) { + String testCpuSet = CPUSetsReader.listToString(cpuSet, 1); + testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, 1); + } + + // Test subset of cpuset with two elements + if (cpuSet.size() >= 2) { + String testCpuSet = CPUSetsReader.listToString(cpuSet, 2); + testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, 2); + testAPCCombo(testCpuSet, 200*1000, 100*1000, 1*1024, 2); + } + } + } + + private static void testActiveProcessorCount(int valueToSet, int expectedValue) throws Exception { Common.logNewTestCase("Test ActiveProcessorCount: valueToSet = " + valueToSet); @@ -99,6 +126,16 @@ public class TestCPUAwareness { } + // Expected active processor count can not exceed available CPU count + private static int adjustExpectedAPCForAvailableCPUs(int expectedAPC) { + if (expectedAPC > availableCPUs) { + expectedAPC = availableCPUs; + System.out.println("Adjusted expectedAPC = " + expectedAPC); + } + return expectedAPC; + } + + private static void testCpuQuotaAndPeriod(int quota, int period) throws Exception { Common.logNewTestCase("test cpu quota and period: "); @@ -107,6 +144,7 @@ public class TestCPUAwareness { int expectedAPC = (int) Math.ceil((float) quota / (float) period); System.out.println("expectedAPC = " + expectedAPC); + expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC); DockerRunOptions opts = Common.newOpts(imageName) .addDockerOpts("--cpu-period=" + period) @@ -129,6 +167,8 @@ public class TestCPUAwareness { System.out.println("shares = " + period); System.out.println("expectedAPC = " + expectedAPC); + expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC); + DockerRunOptions opts = Common.newOpts(imageName) .addDockerOpts("--cpuset-cpus", "" + cpuset) .addDockerOpts("--cpu-period=" + period) @@ -141,6 +181,10 @@ public class TestCPUAwareness { private static void testCpuShares(int shares, int expectedAPC) throws Exception { Common.logNewTestCase("test cpu shares, shares = " + shares); + System.out.println("expectedAPC = " + expectedAPC); + + expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC); + DockerRunOptions opts = Common.newOpts(imageName) .addDockerOpts("--cpu-shares=" + shares); Common.run(opts) diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java index 4c9194e2504..3bcac9bbdf1 100644 --- a/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java +++ b/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java @@ -29,13 +29,17 @@ import java.time.Duration; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + /* * @test HandshakeTransitionTest * @summary This does a sanity test of the poll in the native wrapper. * @requires vm.debug * @library /testlibrary /test/lib * @build HandshakeTransitionTest - * @run main/native HandshakeTransitionTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI HandshakeTransitionTest */ public class HandshakeTransitionTest { @@ -44,6 +48,7 @@ public class HandshakeTransitionTest { public static void main(String[] args) throws Exception { String lib = System.getProperty("test.nativepath"); + WhiteBox wb = WhiteBox.getWhiteBox(); ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( true, @@ -54,6 +59,8 @@ public class HandshakeTransitionTest { "-XX:ParallelGCThreads=1", "-XX:ConcGCThreads=1", "-XX:CICompilerCount=2", + "-XX:+UnlockExperimentalVMOptions", + (wb.getBooleanVMFlag("UseJVMCICompiler") ? "-XX:+UseJVMCICompiler" : "-XX:-UseJVMCICompiler"), "HandshakeTransitionTest$Test"); diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkExitTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkExitTest.java index 1da94483cf8..6a6b16b9e91 100644 --- a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkExitTest.java +++ b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkExitTest.java @@ -42,22 +42,18 @@ public class HandshakeWalkExitTest implements Runnable { } static volatile boolean exit_now = false; - static Thread[] threads; public static void main(String... args) throws Exception { - int testRuns = 100; - int testThreads = 500; + int testRuns = 20; + int testThreads = 128; HandshakeWalkExitTest test = new HandshakeWalkExitTest(); - threads = new Thread[64]; - Runnable hser = new Runnable(){ public void run(){ WhiteBox wb = WhiteBox.getWhiteBox(); while(!exit_now) { wb.handshakeWalkStack(null, true); - try { Thread.sleep(1); } catch(Exception e) {} } } }; diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkOneExitTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkOneExitTest.java new file mode 100644 index 00000000000..45af7e0b95f --- /dev/null +++ b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkOneExitTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, 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 HandshakeWalkOneExitTest + * @summary This test tries to stress the handshakes with new and exiting threads + * @library /testlibrary /test/lib + * @build HandshakeWalkOneExitTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI HandshakeWalkOneExitTest + */ + +import jdk.test.lib.Asserts; +import sun.hotspot.WhiteBox; + +public class HandshakeWalkOneExitTest implements Runnable { + + @Override + public void run() { + } + + static volatile boolean exit_now = false; + static Thread[] threads; + + public static void main(String... args) throws Exception { + int testRuns = 20; + int testThreads = 128; + + HandshakeWalkOneExitTest test = new HandshakeWalkOneExitTest(); + + Runnable hser = new Runnable(){ + public void run(){ + WhiteBox wb = WhiteBox.getWhiteBox(); + while(!exit_now) { + Thread[] t = threads; + for (int i = 0; i +#include + +JNIEXPORT +jint JNICALL Agent_OnAttach(JavaVM *vm, char *options, void *reserved) { + return JNI_ERR; +} diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java new file mode 100644 index 00000000000..32095655640 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.test.lib.apps.LingeredApp; + +/* + * @test + * @bug 8191658 + * @summary Test clhsdb attach, detach, reattach commands + * @library /test/lib + * @run main/othervm ClhsdbAttach + */ + +public class ClhsdbAttach { + + public static void main(String[] args) throws Exception { + System.out.println("Starting ClhsdbAttach test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + theApp = LingeredApp.startApp(); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + String attach = "attach " + theApp.getPid(); + + List cmds = List.of( + "where", + attach, + "flags MaxJavaStackTraceDepth", + "detach", + "universe", + "reattach", + "longConstant markOopDesc::locked_value"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("where", List.of( + "Command not valid until attached to a VM")); + expStrMap.put("flags MaxJavaStackTraceDepth", List.of( + "MaxJavaStackTraceDepth = ")); + expStrMap.put("universe", List.of( + "Command not valid until attached to a VM")); + expStrMap.put("longConstant markOopDesc::locked_value", List.of( + "longConstant markOopDesc::locked_value")); + + test.run(-1, cmds, expStrMap, null); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java new file mode 100644 index 00000000000..280c0e64e4f --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import jdk.test.lib.apps.LingeredApp; + +/* + * @test + * @bug 8191538 + * @summary Test clhsdb 'field' command + * @library /test/lib + * @run main/othervm ClhsdbField + */ + +public class ClhsdbField { + + public static void main(String[] args) throws Exception { + System.out.println("Starting ClhsdbField test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + theApp = LingeredApp.startApp(); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + List cmds = List.of("field"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("field", List.of( + "field ConstantPool _pool_holder InstanceKlass*", + "field InstanceKlass _methods Array*", + "field InstanceKlass _constants ConstantPool*", + "field Klass _name Symbol*", + "field JavaThread _next JavaThread*", + "field JavaThread _osthread OSThread*", + "field JVMState _bci", + "field TenuredGeneration _the_space ContiguousSpace*", + "field VirtualSpace _low_boundary char*", + "field MethodCounters _backedge_counter InvocationCounter", + "field nmethod _entry_bci int", + "field Universe _collectedHeap CollectedHeap")); + test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java new file mode 100644 index 00000000000..76e32a62479 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.Utils; + +/* + * @test + * @bug 8191658 + * @summary Test clhsdb jhisto command + * @library /test/lib + * @run main/othervm ClhsdbJhisto + */ + +public class ClhsdbJhisto { + + public static void main(String[] args) throws Exception { + System.out.println("Starting ClhsdbJhisto test"); + + LingeredAppWithInterface theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + List vmArgs = new ArrayList(); + vmArgs.addAll(Utils.getVmOptions()); + + theApp = new LingeredAppWithInterface(); + LingeredApp.startApp(vmArgs, theApp); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + List cmds = List.of("jhisto"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("jhisto", List.of( + "java.lang.String", + "java.util.HashMap", + "java.lang.Class", + "java.nio.HeapByteBuffer", + "java.net.URI", + "LingeredAppWithInterface", + "ParselTongue", + "ImmutableCollections$SetN$1")); + + test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java index 5366be6f826..2d6ccfd3455 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java @@ -53,10 +53,12 @@ public class ClhsdbLauncher { private void attach(long lingeredAppPid) throws IOException { - System.out.println("Starting clhsdb against " + lingeredAppPid); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); launcher.addToolArg("clhsdb"); - launcher.addToolArg("--pid=" + Long.toString(lingeredAppPid)); + if (lingeredAppPid != -1) { + launcher.addToolArg("--pid=" + Long.toString(lingeredAppPid)); + System.out.println("Starting clhsdb against " + lingeredAppPid); + } ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbolTable.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbolTable.java new file mode 100644 index 00000000000..679d83243ac --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbolTable.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import jdk.test.lib.apps.LingeredApp; + +/* + * @test + * @bug 8191538 + * @summary Test the clhsdb 'symboltable' and 'symbol' commands + * @library /test/lib + * @run main/othervm ClhsdbSymbolTable + */ + +public class ClhsdbSymbolTable { + + public static void main(String[] args) throws Exception { + System.out.println("Starting the ClhsdbSymbolTable test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + + theApp = LingeredApp.startApp(); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + // Test the symboltable command + List cmds = List.of( + "symboltable main", + "symboltable java/lang/Class", + "symboltable java/lang/Object", + "symboltable java/lang/String", + "symboltable java/util/List", + "symboltable jdk/test/lib/apps/LingeredApp"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("symboltable main", List.of( + "sun.jvm.hotspot.oops.Symbol@")); + expStrMap.put("symboltable java/lang/Class", List.of( + "sun.jvm.hotspot.oops.Symbol@")); + expStrMap.put("symboltable java/lang/Object", List.of( + "sun.jvm.hotspot.oops.Symbol@")); + expStrMap.put("symboltable java/lang/String", List.of( + "sun.jvm.hotspot.oops.Symbol@")); + expStrMap.put("symboltable java/util/List", List.of( + "sun.jvm.hotspot.oops.Symbol@")); + expStrMap.put("symboltable jdk/test/lib/apps/LingeredApp", List.of( + "sun.jvm.hotspot.oops.Symbol@")); + String consolidatedOutput = + test.run(theApp.getPid(), cmds, expStrMap, null); + + // Test the 'symbol' command passing in the address obtained from + // the 'symboltable' command + expStrMap = new HashMap<>(); + cmds = new ArrayList(); + int expectedStringsIdx = 0; + String expectedStrings[] = {"#main", + "#java/lang/Class", "#java/lang/Object", + "#java/lang/String", "#java/util/List", + "#jdk/test/lib/apps/LingeredApp"}; + if (consolidatedOutput != null) { + // Output could be null due to attach permission issues + // and if we are skipping this. + String[] singleCommandOutputs = consolidatedOutput.split("hsdb>"); + + for (String singleCommandOutput : singleCommandOutputs) { + if (singleCommandOutput.contains("@")) { + String[] tokens = singleCommandOutput.split("@"); + String addressString = tokens[1].replace("\n",""); + + // tokens[1] represents the address of the symbol + String cmd = "symbol " + addressString; + cmds.add(cmd); + expStrMap.put(cmd, List.of + (expectedStrings[expectedStringsIdx++])); + } + } + test.run(theApp.getPid(), cmds, expStrMap, null); + } + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java new file mode 100644 index 00000000000..02e832d885f --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import jdk.test.lib.apps.LingeredApp; + +/* + * @test + * @bug 8191538 + * @summary Test clhsdb 'vmstructsdump' command + * @library /test/lib + * @run main/othervm ClhsdbVmStructsDump + */ + +public class ClhsdbVmStructsDump { + + public static void main(String[] args) throws Exception { + System.out.println("Starting ClhsdbVmStructsDump test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + theApp = LingeredApp.startApp(); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + List cmds = List.of("vmstructsdump"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("vmstructsdump", List.of( + "field ConstantPool _pool_holder InstanceKlass*", + "field InstanceKlass _methods Array*", + "field InstanceKlass _constants ConstantPool*", + "field Klass _name Symbol*", + "type ClassLoaderData* null", + "type DictionaryEntry KlassHashtableEntry", + "field JavaThread _next JavaThread*", + "field JavaThread _osthread OSThread*", + "type TenuredGeneration CardGeneration", + "field JVMState _bci", + "type Universe null", + "type ConstantPoolCache MetaspaceObj")); + test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java index 0c916001288..000e8081993 100644 --- a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java +++ b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java @@ -56,10 +56,10 @@ public class JhsdbThreadInfoTest { pb.command(jhsdbLauncher.getCommand()); Process jhsdb = pb.start(); - jhsdb.waitFor(); - OutputAnalyzer out = new OutputAnalyzer(jhsdb); + jhsdb.waitFor(); + System.out.println(out.getStdout()); System.err.println(out.getStderr()); diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java new file mode 100644 index 00000000000..9acf9d3bbb9 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.apps.LingeredApp; + + +public class LingeredAppWithLock extends LingeredApp { + + public static void lockMethod(Object lock) { + synchronized (lock) { + try { + Thread.sleep(300000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + public static void main(String args[]) { + Thread classLock1 = new Thread(() -> lockMethod(LingeredAppWithLock.class)); + Thread classLock2 = new Thread(() -> lockMethod(LingeredAppWithLock.class)); + Thread objectLock = new Thread(() -> lockMethod(classLock1)); + Thread primitiveLock = new Thread(() -> lockMethod(int.class)); + + classLock1.start(); + classLock2.start(); + objectLock.start(); + primitiveLock.start(); + + LingeredApp.main(args); + } + } diff --git a/test/hotspot/jtreg/serviceability/sa/TestClassDump.java b/test/hotspot/jtreg/serviceability/sa/TestClassDump.java new file mode 100644 index 00000000000..cdaa3de6c64 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/TestClassDump.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @bug 8184982 + * @summary Test ClassDump tool + * @library /test/lib + * @run main/othervm TestClassDump + */ + +public class TestClassDump { + + private static void dumpClass(long lingeredAppPid) + throws IOException { + + ProcessBuilder pb; + OutputAnalyzer output; + + pb = ProcessTools.createJavaProcessBuilder( + "-Dsun.jvm.hotspot.tools.jcore.outputDir=jtreg_classes", + "-m", "jdk.hotspot.agent/sun.jvm.hotspot.tools.jcore.ClassDump", String.valueOf(lingeredAppPid)); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + if (!Files.isDirectory(Paths.get("jtreg_classes"))) { + throw new RuntimeException("jtreg_classes directory not found"); + } + if (Files.notExists(Paths.get("jtreg_classes", "java", "lang", "Integer.class"))) { + throw new RuntimeException("jtreg_classes/java/lang/Integer.class not found"); + } + if (Files.notExists(Paths.get("jtreg_classes", "jdk", "test", "lib", "apps", "LingeredApp.class"))) { + throw new RuntimeException("jtreg_classes/jdk/test/lib/apps/LingeredApp.class not found"); + } + if (Files.notExists(Paths.get("jtreg_classes", "sun", "net", "util", "URLUtil.class"))) { + throw new RuntimeException("jtreg_classes/sun/net/util/URLUtil.class not found"); + } + + pb = ProcessTools.createJavaProcessBuilder( + "-Dsun.jvm.hotspot.tools.jcore.outputDir=jtreg_classes2", + "-Dsun.jvm.hotspot.tools.jcore.PackageNameFilter.pkgList=jdk,sun", + "-m", "jdk.hotspot.agent/sun.jvm.hotspot.tools.jcore.ClassDump", String.valueOf(lingeredAppPid)); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + if (Files.exists(Paths.get("jtreg_classes2", "java", "math", "BigInteger.class"))) { + throw new RuntimeException("jtreg_classes2/java/math/BigInteger.class not expected"); + } + if (Files.notExists(Paths.get("jtreg_classes2", "sun", "util", "calendar", "BaseCalendar.class"))) { + throw new RuntimeException("jtreg_classes2/sun/util/calendar/BaseCalendar.class not found"); + } + if (Files.notExists(Paths.get("jtreg_classes2", "jdk", "internal", "vm", "PostVMInitHook.class"))) { + throw new RuntimeException("jtreg_classes2/jdk/internal/vm/PostVMInitHook.class not found"); + } + } + + public static void main(String[] args) throws Exception { + if (!Platform.shouldSAAttach()) { + // Silently skip the test if we don't have enough permissions to attach + System.out.println("SA attach not expected to work - test skipped."); + return; + } + + LingeredApp theApp = null; + try { + theApp = LingeredApp.startApp(); + long pid = theApp.getPid(); + System.out.println("Started LingeredApp with pid " + pid); + dumpClass(pid); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java b/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java new file mode 100644 index 00000000000..5f9a43f3267 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.Scanner; +import java.util.List; +import java.io.File; +import java.io.IOException; +import java.util.stream.Collectors; +import java.io.OutputStream; +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Utils; +import jdk.test.lib.Asserts; + +/* + * @test + * @library /test/lib + * @run main/othervm TestClhsdbJstackLock + */ + +public class TestClhsdbJstackLock { + + private static final String JSTACK_OUT_FILE = "jstack_out.txt"; + + private static void verifyJStackOutput() throws Exception { + + Exception unexpected = null; + File jstackFile = new File(JSTACK_OUT_FILE); + Asserts.assertTrue(jstackFile.exists() && jstackFile.isFile(), + "File with jstack output not created: " + + jstackFile.getAbsolutePath()); + try { + Scanner scanner = new Scanner(jstackFile); + + boolean classLockOwnerFound = false; + boolean classLockWaiterFound = false; + boolean objectLockOwnerFound = false; + boolean primitiveLockOwnerFound = false; + + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + System.out.println(line); + + if (line.contains("missing reason for ")) { + unexpected = new RuntimeException("Unexpected msg: missing reason for "); + break; + } + if (line.matches("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$")) { + classLockOwnerFound = true; + } + if (line.matches("^\\s+- waiting to lock <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$")) { + classLockWaiterFound = true; + } + if (line.matches("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Thread\\)$")) { + objectLockOwnerFound = true; + } + if (line.matches("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for int\\)$")) { + primitiveLockOwnerFound = true; + } + } + + if (!classLockOwnerFound || !classLockWaiterFound || + !objectLockOwnerFound || !primitiveLockOwnerFound) { + unexpected = new RuntimeException( + "classLockOwnerFound = " + classLockOwnerFound + + ", classLockWaiterFound = " + classLockWaiterFound + + ", objectLockOwnerFound = " + objectLockOwnerFound + + ", primitiveLockOwnerFound = " + primitiveLockOwnerFound); + } + if (unexpected != null) { + throw unexpected; + } + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + jstackFile.delete(); + } + } + + private static void startClhsdbForLock(long lingeredAppPid) throws Exception { + + Process p; + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + launcher.addToolArg("clhsdb"); + launcher.addToolArg("--pid"); + launcher.addToolArg(Long.toString(lingeredAppPid)); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(launcher.getCommand()); + System.out.println(pb.command().stream().collect(Collectors.joining(" "))); + + try { + p = pb.start(); + } catch (Exception attachE) { + throw new Error("Couldn't start jhsdb or attach to LingeredApp : " + attachE); + } + + // Issue the 'jstack' input at the clhsdb prompt. + OutputStream input = p.getOutputStream(); + String str = "jstack > " + JSTACK_OUT_FILE + "\nquit\n"; + try { + input.write(str.getBytes()); + input.flush(); + } catch (IOException ioe) { + throw new Error("Problem issuing the jstack command: " + str, ioe); + } + + OutputAnalyzer output = new OutputAnalyzer(p); + + try { + p.waitFor(); + } catch (InterruptedException ie) { + p.destroyForcibly(); + throw new Error("Problem awaiting the child process: " + ie, ie); + } + + output.shouldHaveExitValue(0); + } + + public static void main (String... args) throws Exception { + + LingeredApp app = null; + + if (!Platform.shouldSAAttach()) { + System.out.println("SA attach not expected to work - test skipped."); + return; + } + + try { + List vmArgs = new ArrayList(Utils.getVmOptions()); + + app = new LingeredAppWithLock(); + LingeredApp.startApp(vmArgs, app); + System.out.println ("Started LingeredApp with pid " + app.getPid()); + startClhsdbForLock(app.getPid()); + verifyJStackOutput(); + } finally { + LingeredApp.stopApp(app); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java new file mode 100644 index 00000000000..739ae29ba0b --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.Asserts; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.Utils; + +/* + * @test + * @library /test/lib + * @run main/othervm TestJhsdbJstackLock + */ + +public class TestJhsdbJstackLock { + + public static void main (String... args) throws Exception { + + LingeredApp app = null; + + if (!Platform.shouldSAAttach()) { + System.out.println("SA attach not expected to work - test skipped."); + return; + } + + try { + List vmArgs = new ArrayList(Utils.getVmOptions()); + + app = new LingeredAppWithLock(); + LingeredApp.startApp(vmArgs, app); + System.out.println ("Started LingeredApp with pid " + app.getPid()); + + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + launcher.addToolArg("jstack"); + launcher.addToolArg("--pid"); + launcher.addToolArg(Long.toString(app.getPid())); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(launcher.getCommand()); + Process jhsdb = pb.start(); + OutputAnalyzer out = new OutputAnalyzer(jhsdb); + + jhsdb.waitFor(); + + System.out.println(out.getStdout()); + System.err.println(out.getStderr()); + + out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$"); + out.shouldMatch("^\\s+- waiting to lock <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$"); + out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Thread\\)$"); + out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for int\\)$"); + out.stderrShouldBeEmpty(); + + System.out.println("Test Completed"); + } finally { + LingeredApp.stopApp(app); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/TestPrintMdo.java b/test/hotspot/jtreg/serviceability/sa/TestPrintMdo.java index 48b0b0840b8..56e18f0409a 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestPrintMdo.java +++ b/test/hotspot/jtreg/serviceability/sa/TestPrintMdo.java @@ -132,22 +132,16 @@ public class TestPrintMdo { throw new Error("Problem issuing the printmdo command: " + str, ioe); } + OutputAnalyzer output = new OutputAnalyzer(p); + try { p.waitFor(); } catch (InterruptedException ie) { + p.destroyForcibly(); throw new Error("Problem awaiting the child process: " + ie, ie); } - int exitValue = p.exitValue(); - if (exitValue != 0) { - String output; - try { - output = new OutputAnalyzer(p).getOutput(); - } catch (IOException ioe) { - throw new Error("Can't get failed clhsdb process output: " + ioe, ioe); - } - throw new AssertionError("clhsdb wasn't run successfully: " + output); - } + output.shouldHaveExitValue(0); } public static void main (String... args) throws Exception { diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index 453c3c0c612..cdc8efaedfb 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -123,14 +123,15 @@ public class CtwRunner { .collect(Collectors.joining(" ")); String phase = phaseName(classStart); Path out = Paths.get(".", phase + ".out"); + Path err = Paths.get(".", phase + ".err"); System.out.printf("%s %dms START : [%s]%n" + "cout/cerr are redirected to %s%n", phase, TimeUnit.NANOSECONDS.toMillis(System.nanoTime()), - commandLine, out); - int exitCode = pb.redirectErrorStream(true) - .redirectOutput(out.toFile()) - .start() - .waitFor(); + commandLine, phase); + int exitCode = pb.redirectOutput(out.toFile()) + .redirectError(err.toFile()) + .start() + .waitFor(); System.out.printf("%s %dms END : exit code = %d%n", phase, TimeUnit.NANOSECONDS.toMillis(System.nanoTime()), exitCode); diff --git a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java index 9903b188e62..fc563ee2368 100644 --- a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java +++ b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java @@ -51,7 +51,7 @@ public class TestMutuallyExclusivePlatformPredicates { VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"), MODE("isInt", "isMixed", "isComp"), IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild", "isSlowDebugBuild", - "shouldSAAttach", "isTieredSupported"); + "shouldSAAttach", "isTieredSupported", "areCustomLoadersSupportedForCDS"); public final List methodNames; @@ -106,7 +106,7 @@ public class TestMutuallyExclusivePlatformPredicates { && m.getReturnType() == boolean.class) { Asserts.assertTrue(allMethods.contains(m.getName()), "All Platform's methods with signature '():Z' should " - + "be tested "); + + "be tested. Missing: " + m.getName()); } } } diff --git a/test/jdk/com/sun/tools/attach/StartManagementAgent.java b/test/jdk/com/sun/tools/attach/StartManagementAgent.java index 1a5234b3408..bd996ea2c63 100644 --- a/test/jdk/com/sun/tools/attach/StartManagementAgent.java +++ b/test/jdk/com/sun/tools/attach/StartManagementAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -99,7 +99,7 @@ public class StartManagementAgent { } catch(AttachOperationFailedException ex) { // We expect parsing of "apa" above to fail, but if the file path // can't be read we get a different exception message - if (!ex.getMessage().contains("Invalid com.sun.management.jmxremote.port number")) { + if (!ex.getMessage().contains("NumberFormatException: For input string: \"apa\"")) { throw ex; } ex.printStackTrace(System.err); diff --git a/test/jdk/javax/management/security/HashedPasswordFileTest.java b/test/jdk/javax/management/security/HashedPasswordFileTest.java new file mode 100644 index 00000000000..cae574c36a6 --- /dev/null +++ b/test/jdk/javax/management/security/HashedPasswordFileTest.java @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2017, 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 5016517 + * @summary Test Hashed passwords + * @library /test/lib + * @modules java.management + * @build HashedPasswordFileTest + * @run testng/othervm HashedPasswordFileTest + * + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.net.MalformedURLException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.attribute.PosixFilePermission; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.*; +import javax.management.MBeanServer; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +import org.testng.Assert; +import org.testng.annotations.Test; +import org.testng.annotations.AfterClass; + +import jdk.test.lib.Utils; +import jdk.test.lib.process.ProcessTools; + +@Test +public class HashedPasswordFileTest { + + private final String[] randomWords = {"accost", "savoie", "bogart", "merest", + "azuela", "hoodie", "bursal", "lingua", "wincey", "trilby", "egesta", + "wester", "gilgai", "weinek", "ochone", "sanest", "gainst", "defang", + "ranket", "mayhem", "tagger", "timber", "eggcup", "mhren", "colloq", + "dreamy", "hattie", "rootle", "bloody", "helyne", "beater", "cosine", + "enmity", "outbox", "issuer", "lumina", "dekker", "vetoed", "dennis", + "strove", "gurnet", "talkie", "bennie", "behove", "coates", "shiloh", + "yemeni", "boleyn", "coaxal", "irne"}; + + private final String[] hashAlgs = { + "MD2", + "MD5", + "SHA-1", + "SHA-224", + "SHA-256", + "SHA-384", + "SHA-512/224", + "SHA-512/256", + "SHA3-224", + "SHA3-256", + "SHA3-384", + "SHA3-512" + }; + + private final Random rnd = new Random(); + private final Random random = Utils.getRandomInstance(); + + private JMXConnectorServer cs; + + private String randomWord() { + int idx = rnd.nextInt(randomWords.length); + return randomWords[idx]; + } + + private String[] getHash(String algorithm, String password) { + try { + byte[] salt = new byte[64]; + random.nextBytes(salt); + + MessageDigest digest = MessageDigest.getInstance(algorithm); + digest.reset(); + digest.update(salt); + byte[] hash = digest.digest(password.getBytes(StandardCharsets.UTF_8)); + + String saltStr = Base64.getEncoder().encodeToString(salt); + String hashStr = Base64.getEncoder().encodeToString(hash); + + return new String[]{saltStr, hashStr}; + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } + + private String getPasswordFilePath() { + String testDir = System.getProperty("test.src"); + String testFileName = "jmxremote.password"; + return testDir + File.separator + testFileName; + } + + private File createNewPasswordFile() throws IOException { + File file = new File(getPasswordFilePath()); + if (file.exists()) { + file.delete(); + } + file.createNewFile(); + return file; + } + + private Map generateClearTextPasswordFile() throws IOException { + File file = createNewPasswordFile(); + Map props = new HashMap<>(); + BufferedWriter br; + try (FileWriter fw = new FileWriter(file)) { + br = new BufferedWriter(fw); + int numentries = rnd.nextInt(5) + 3; + for (int i = 0; i < numentries; i++) { + String username = randomWord(); + String password = randomWord(); + props.put(username, password); + br.write(username + " " + password + "\n"); + } + br.flush(); + } + br.close(); + return props; + } + + private boolean isPasswordFileHashed() throws IOException { + BufferedReader br; + boolean result; + try (FileReader fr = new FileReader(getPasswordFilePath())) { + br = new BufferedReader(fr); + result = br.lines().anyMatch(line -> { + if (line.startsWith("#")) { + return false; + } + String[] tokens = line.split("\\s+"); + return tokens.length == 3 || tokens.length == 4; + }); + } + br.close(); + return result; + } + + private Map generateHashedPasswordFile() throws IOException { + File file = createNewPasswordFile(); + Map props = new HashMap<>(); + BufferedWriter br; + try (FileWriter fw = new FileWriter(file)) { + br = new BufferedWriter(fw); + int numentries = rnd.nextInt(5) + 3; + for (int i = 0; i < numentries; i++) { + String username = randomWord(); + String password = randomWord(); + String alg = hashAlgs[rnd.nextInt(hashAlgs.length)]; + String[] b64str = getHash(alg, password); + br.write(username + " " + b64str[0] + " " + b64str[1] + " " + alg + "\n"); + props.put(username, password); + } + br.flush(); + } + br.close(); + return props; + } + + private JMXServiceURL createServerSide(boolean useHash) + throws IOException { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + + HashMap env = new HashMap<>(); + env.put("jmx.remote.x.password.file", getPasswordFilePath()); + env.put("jmx.remote.x.password.toHashes", useHash ? "true" : "false"); + cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); + cs.start(); + return cs.getAddress(); + } + + @Test + public void testClearTextPasswordFile() throws IOException { + Boolean[] bvals = new Boolean[]{true, false}; + for (boolean bval : bvals) { + try { + Map credentials = generateClearTextPasswordFile(); + JMXServiceURL serverUrl = createServerSide(bval); + for (Map.Entry entry : credentials.entrySet()) { + HashMap env = new HashMap<>(); + env.put("jmx.remote.credentials", + new String[]{entry.getKey(), entry.getValue()}); + try (JMXConnector cc = JMXConnectorFactory.connect(serverUrl, env)) { + cc.getMBeanServerConnection(); + } + } + Assert.assertEquals(isPasswordFileHashed(), bval); + } finally { + cs.stop(); + } + } + } + + @Test + public void testReadOnlyPasswordFile() throws IOException { + Boolean[] bvals = new Boolean[]{true, false}; + for (boolean bval : bvals) { + try { + Map credentials = generateClearTextPasswordFile(); + File file = new File(getPasswordFilePath()); + file.setReadOnly(); + JMXServiceURL serverUrl = createServerSide(bval); + for (Map.Entry entry : credentials.entrySet()) { + HashMap env = new HashMap<>(); + env.put("jmx.remote.credentials", + new String[]{entry.getKey(), entry.getValue()}); + try (JMXConnector cc = JMXConnectorFactory.connect(serverUrl, env)) { + cc.getMBeanServerConnection(); + } + } + Assert.assertEquals(isPasswordFileHashed(), false); + } finally { + cs.stop(); + } + } + } + + @Test + public void testHashedPasswordFile() throws IOException { + Boolean[] bvals = new Boolean[]{true, false}; + for (boolean bval : bvals) { + try { + Map credentials = generateHashedPasswordFile(); + JMXServiceURL serverUrl = createServerSide(bval); + Assert.assertEquals(isPasswordFileHashed(), true); + for (Map.Entry entry : credentials.entrySet()) { + HashMap env = new HashMap<>(); + env.put("jmx.remote.credentials", + new String[]{entry.getKey(), entry.getValue()}); + try (JMXConnector cc = JMXConnectorFactory.connect(serverUrl, env)) { + cc.getMBeanServerConnection(); + } + } + } finally { + cs.stop(); + } + } + } + + private static class SimpleJMXClient implements Callable { + private final JMXServiceURL url; + private final Map credentials; + + public SimpleJMXClient(JMXServiceURL url, Map credentials) { + this.url = url; + this.credentials = credentials; + } + + @Override + public Object call() throws Exception { + for (Map.Entry entry : credentials.entrySet()) { + HashMap env = new HashMap<>(); + env.put("jmx.remote.credentials", + new String[]{entry.getKey(), entry.getValue()}); + try (JMXConnector cc = JMXConnectorFactory.connect(url, env)) { + cc.getMBeanServerConnection(); + } + } + return null; + } + } + + @Test + public void testMultipleClients() throws Throwable { + Map credentials = generateClearTextPasswordFile(); + JMXServiceURL serverUrl = createServerSide(true); + Assert.assertEquals(isPasswordFileHashed(), false); + // create random number of clients + int numClients = rnd.nextInt(20) + 10; + List futures = new ArrayList<>(); + ExecutorService executor = Executors.newFixedThreadPool(numClients); + for (int i = 0; i < numClients; i++) { + Future future = executor.submit(new SimpleJMXClient(serverUrl, credentials)); + futures.add(future); + } + try { + for (Future future : futures) { + future.get(); + } + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } catch (ExecutionException ex) { + throw ex.getCause(); + } finally { + executor.shutdown(); + } + + Assert.assertEquals(isPasswordFileHashed(), true); + } + + @Test + public void testPasswordChange() throws IOException { + try { + Map credentials = generateClearTextPasswordFile(); + JMXServiceURL serverUrl = createServerSide(true); + Assert.assertEquals(isPasswordFileHashed(), false); + + for (Map.Entry entry : credentials.entrySet()) { + HashMap env = new HashMap<>(); + env.put("jmx.remote.credentials", + new String[]{entry.getKey(), entry.getValue()}); + try (JMXConnector cc = JMXConnectorFactory.connect(serverUrl, env)) { + cc.getMBeanServerConnection(); + } + } + Assert.assertEquals(isPasswordFileHashed(), true); + + // Read the file back. Add new entries. Change passwords for few + BufferedReader br = new BufferedReader(new FileReader(getPasswordFilePath())); + String line; + StringBuilder sbuild = new StringBuilder(); + while ((line = br.readLine()) != null) { + if (line.trim().startsWith("#")) { + sbuild.append(line).append("\n"); + continue; + } + String[] tokens = line.split("\\s+"); + // Change password for random entries + if ((tokens.length == 4 || tokens.length == 3) && rnd.nextBoolean()) { + String password = randomWord(); + credentials.put(tokens[0], password); + sbuild.append(tokens[0]).append(" ").append(password).append("\n"); + } else { + sbuild.append(line).append("\n"); + } + } + + // Add new entries in clear + int newentries = rnd.nextInt(2) + 3; + for (int i = 0; i < newentries; i++) { + String username = randomWord(); + String password = randomWord(); + credentials.put(username, password); + sbuild.append(username).append(" ").append(password).append("\n"); + } + + // Add new entries as a hash + int numentries = rnd.nextInt(2) + 3; + for (int i = 0; i < numentries; i++) { + String username = randomWord(); + String password = randomWord(); + String alg = hashAlgs[rnd.nextInt(hashAlgs.length)]; + String[] b64str = getHash(alg, password); + credentials.put(username, password); + sbuild.append(username).append(" ").append(b64str[0]) + .append(" ").append(b64str[1]).append(" ") + .append(alg).append("\n"); + } + + try (BufferedWriter bw = new BufferedWriter(new FileWriter(getPasswordFilePath()))) { + bw.write(sbuild.toString()); + } + + for (Map.Entry entry : credentials.entrySet()) { + HashMap env = new HashMap<>(); + env.put("jmx.remote.credentials", + new String[]{entry.getKey(), entry.getValue()}); + try (JMXConnector cc = JMXConnectorFactory.connect(serverUrl, env)) { + cc.getMBeanServerConnection(); + } + } + } finally { + cs.stop(); + } + } + + @Test + public void testDefaultAgent() throws Exception { + List pbArgs = new ArrayList<>(); + int port = Utils.getFreePort(); + generateClearTextPasswordFile(); + + // This will run only on a POSIX compliant system + if (!FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { + return; + } + + // Make sure only owner is able to read/write the file or else + // default agent will fail to start + File file = new File(getPasswordFilePath()); + Set perms = new HashSet<>(); + perms.add(PosixFilePermission.OWNER_READ); + perms.add(PosixFilePermission.OWNER_WRITE); + Files.setPosixFilePermissions(file.toPath(), perms); + + pbArgs.add("-cp"); + pbArgs.add(System.getProperty("test.class.path")); + + pbArgs.add("-Dcom.sun.management.jmxremote.port=" + port); + pbArgs.add("-Dcom.sun.management.jmxremote.authenticate=true"); + pbArgs.add("-Dcom.sun.management.jmxremote.password.file=" + file.getAbsolutePath()); + pbArgs.add("-Dcom.sun.management.jmxremote.ssl=false"); + pbArgs.add(TestApp.class.getSimpleName()); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + pbArgs.toArray(new String[0])); + Process process = ProcessTools.startProcess( + TestApp.class.getSimpleName(), + pb); + + if (process.waitFor() != 0) { + throw new RuntimeException("Test Failed : Error starting default agent"); + } + Assert.assertEquals(isPasswordFileHashed(), true); + } + + @Test + public void testDefaultAgentNoHash() throws Exception { + List pbArgs = new ArrayList<>(); + int port = Utils.getFreePort(); + generateClearTextPasswordFile(); + + // This will run only on a POSIX compliant system + if (!FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { + return; + } + + // Make sure only owner is able to read/write the file or else + // default agent will fail to start + File file = new File(getPasswordFilePath()); + Set perms = new HashSet<>(); + perms.add(PosixFilePermission.OWNER_READ); + perms.add(PosixFilePermission.OWNER_WRITE); + Files.setPosixFilePermissions(file.toPath(), perms); + + pbArgs.add("-cp"); + pbArgs.add(System.getProperty("test.class.path")); + + pbArgs.add("-Dcom.sun.management.jmxremote.port=" + port); + pbArgs.add("-Dcom.sun.management.jmxremote.authenticate=true"); + pbArgs.add("-Dcom.sun.management.jmxremote.password.file=" + file.getAbsolutePath()); + pbArgs.add("-Dcom.sun.management.jmxremote.password.toHashes=false"); + pbArgs.add("-Dcom.sun.management.jmxremote.ssl=false"); + pbArgs.add(TestApp.class.getSimpleName()); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + pbArgs.toArray(new String[0])); + Process process = ProcessTools.startProcess( + TestApp.class.getSimpleName(), + pb); + + if (process.waitFor() != 0) { + throw new RuntimeException("Test Failed : Error starting default agent"); + } + Assert.assertEquals(isPasswordFileHashed(), false); + } + + @AfterClass + public void cleanUp() { + File file = new File(getPasswordFilePath()); + if (file.exists()) { + file.delete(); + } + } +} + +class TestApp { + + public static void main(String[] args) throws IOException { + try { + JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + + System.getProperty("com.sun.management.jmxremote.port") + "/jmxrmi"); + Map env = new HashMap<>(1); + // any dummy credentials will do. We just have to trigger password hashing + env.put("jmx.remote.credentials", new String[]{"a", "a"}); + try (JMXConnector cc = JMXConnectorFactory.connect(url, env)) { + cc.getMBeanServerConnection(); + } + } catch (SecurityException ex) { + // Catch authentication failure here + } + } +} diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 13632fe7abe..215e143b610 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -74,6 +74,7 @@ public class VMProps implements Callable> { map.put("vm.aot", vmAOT()); // vm.cds is true if the VM is compiled with cds support. map.put("vm.cds", vmCDS()); + map.put("vm.cds.custom.loaders", vmCDSForCustomLoaders()); // vm.graal.enabled is true if Graal is used as JIT map.put("vm.graal.enabled", isGraalEnabled()); map.put("docker.support", dockerSupport()); @@ -296,6 +297,19 @@ public class VMProps implements Callable> { } } + /** + * Check for CDS support for custom loaders. + * + * @return true if CDS is supported for customer loader by the VM to be tested. + */ + protected String vmCDSForCustomLoaders() { + if (vmCDS().equals("true") && Platform.areCustomLoadersSupportedForCDS()) { + return "true"; + } else { + return "false"; + } + } + /** * Check if Graal is used as JIT compiler. * diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 16cfc52ccbd..d38a137068e 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -288,4 +288,16 @@ public class Platform { return "so"; } } + + /* + * This should match the #if condition in ClassListParser::load_class_from_source(). + */ + public static boolean areCustomLoadersSupportedForCDS() { + boolean isLinux = Platform.isLinux(); + boolean is64 = Platform.is64bit(); + boolean isSolaris = Platform.isSolaris(); + boolean isAix = Platform.isAix(); + + return (is64 && (isLinux || isSolaris || isAix)); + } } diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index 8d0f9ef4bcb..5b1dd1846f8 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -166,9 +166,9 @@ public class CDSTestUtils { outStr.contains("Unable to map ReadWrite shared space at required address") || outStr.contains("Unable to map MiscData shared space at required address") || outStr.contains("Unable to map MiscCode shared space at required address") || - outStr.contains("Unable to map shared string space at required address") || + outStr.contains("Unable to map OptionalData shared space at required address") || outStr.contains("Could not allocate metaspace at a compatible address") || - outStr.contains("Unable to allocate shared string space: range is not within java heap") )) + outStr.contains("UseSharedSpaces: Unable to allocate region, range is not within java heap") )) { return true; }