diff --git a/.jcheck/conf b/.jcheck/conf index 49d527e3b81..01cc62ca93b 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -27,11 +27,32 @@ repository=amber jbs=jdk [checks] -error=author,committer,whitespace,executable,symlink +error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists + +[repository] +tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d) +branches= [census] version=0 domain=openjdk.org [checks "whitespace"] -files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java +files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm + +[checks "merge"] +message=Merge + +[checks "reviewers"] +reviewers=1 +ignore=duke + +[checks "committer"] +role=committer + +[checks "issues"] +pattern=^([124-8][0-9]{6}): (\S.*)$ + + +[checks "problemlists"] +dirs=test/jdk|test/langtools|test/lib-test|test/hotspot/jtreg|test/jaxp diff --git a/make/hotspot/lib/JvmFeatures.gmk b/make/hotspot/lib/JvmFeatures.gmk index 17964d84f2c..3647806e1d7 100644 --- a/make/hotspot/lib/JvmFeatures.gmk +++ b/make/hotspot/lib/JvmFeatures.gmk @@ -119,7 +119,9 @@ ifneq ($(call check-jvm-feature, cds), true) archiveBuilder.cpp \ archiveUtils.cpp \ classListParser.cpp \ + classLoaderDataShared.cpp \ classLoaderExt.cpp \ + cppVtables.cpp \ dumpAllocStats.cpp \ dynamicArchive.cpp \ filemap.cpp \ diff --git a/make/hotspot/symbols/symbols-unix b/make/hotspot/symbols/symbols-unix index b462929c02e..de444eae41c 100644 --- a/make/hotspot/symbols/symbols-unix +++ b/make/hotspot/symbols/symbols-unix @@ -198,5 +198,6 @@ JVM_AddModuleExports JVM_AddModuleExportsToAll JVM_AddModuleExportsToAllUnnamed JVM_AddReadsModule +JVM_DefineArchivedModules JVM_DefineModule JVM_SetBootLoaderUnnamedModule diff --git a/make/scripts/generate-symbol-data.sh b/make/scripts/generate-symbol-data.sh index 3ce684041dc..56aa8016dd6 100644 --- a/make/scripts/generate-symbol-data.sh +++ b/make/scripts/generate-symbol-data.sh @@ -63,7 +63,7 @@ if [ ! -f symbols ] ; then exit 1 fi; -if [ "`hg status .`x" != "x" ] ; then +if [ "`git status --porcelain=v1 .`x" != "x" ] ; then echo "The make/data/symbols directory contains local changes!" >&2 exit 1 fi; diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index fb9929e2f97..5970a898bf2 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -614,8 +614,8 @@ alloc_class chunk3(RFLAGS); // Several register classes are automatically defined based upon information in // this architecture description. // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ ) -// 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ ) -// 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ ) +// 2) reg_class compiler_method_reg ( /* as def'd in frame section */ ) +// 2) reg_class interpreter_method_reg ( /* as def'd in frame section */ ) // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) // @@ -2410,12 +2410,6 @@ const int Matcher::float_pressure(int default_pressure_threshold) { return default_pressure_threshold; } -int Matcher::regnum_to_fpu_offset(int regnum) -{ - Unimplemented(); - return 0; -} - // Is this branch offset short enough that a short branch can be used? // // NOTE: If the platform does not provide any short branch variants, then @@ -4043,17 +4037,14 @@ encode %{ // SP meets the minimum alignment. frame %{ - // What direction does stack grow in (assumed to be same for C & Java) - stack_direction(TOWARDS_LOW); - // These three registers define part of the calling convention // between compiled code and the interpreter. // Inline Cache Register or Method for I2C. inline_cache_reg(R12); - // Method Oop Register when calling interpreter. - interpreter_method_oop_reg(R12); + // Method Register when calling interpreter. + interpreter_method_reg(R12); // Number of stack slots consumed by locking an object sync_stack_slots(2); @@ -5622,9 +5613,9 @@ operand inline_cache_RegP(iRegP reg) interface(REG_INTER); %} -operand interpreter_method_oop_RegP(iRegP reg) +operand interpreter_method_RegP(iRegP reg) %{ - constraint(ALLOC_IN_RC(method_reg)); // interpreter_method_oop_reg + constraint(ALLOC_IN_RC(method_reg)); // interpreter_method_reg match(reg); match(iRegPNoSp); op_cost(0); diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp index 4ab358a23de..99b213ddab4 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp @@ -101,7 +101,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { frame_pointers_t *new_frame = (frame_pointers_t *)(return_address_ptr - 5); - JavaThread *thread = (JavaThread*)Thread::current(); + JavaThread *thread = JavaThread::current(); RegisterMap reg_map(thread, false); frame frame = thread->last_frame(); @@ -111,14 +111,11 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { LogTarget(Trace, nmethod, barrier) out; if (out.is_enabled()) { - Thread* thread = Thread::current(); - assert(thread->is_Java_thread(), "must be JavaThread"); - JavaThread* jth = (JavaThread*) thread; ResourceMark mark; log_trace(nmethod, barrier)("deoptimize(nmethod: %s(%p), return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p", nm->method()->name_and_sig_as_C_string(), - nm, *(address *) return_address_ptr, nm->is_osr_method(), jth, - jth->get_thread_name(), frame.sp(), nm->verified_entry_point()); + nm, *(address *) return_address_ptr, nm->is_osr_method(), thread, + thread->get_thread_name(), frame.sp(), nm->verified_entry_point()); } new_frame->sp = frame.sp(); diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index 90e76e507e8..294b6b13495 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -75,13 +75,11 @@ define_pd_global(intx, InitArrayShortSize, BytesPerLong); define_pd_global(intx, InlineSmallCode, 1000); #endif -#define ARCH_FLAGS(develop, \ - product, \ - diagnostic, \ - experimental, \ - notproduct, \ - range, \ - constraint) \ +#define ARCH_FLAGS(develop, \ + product, \ + notproduct, \ + range, \ + constraint) \ \ product(bool, NearCpool, true, \ "constant pool is close to instructions") \ @@ -113,4 +111,6 @@ define_pd_global(intx, InlineSmallCode, 1000); "Value -1 means off.") \ range(-1, 4096) +// end of ARCH_FLAGS + #endif // CPU_AARCH64_GLOBALS_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 3cbf025b0c7..decc17d1958 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -28,6 +28,7 @@ #include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 9870b24ecb5..5dde5e89946 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -27,7 +27,6 @@ #define CPU_AARCH64_VM_VERSION_AARCH64_HPP #include "runtime/abstract_vm_version.hpp" -#include "runtime/globals_extension.hpp" #include "utilities/sizes.hpp" class VM_Version : public Abstract_VM_Version { diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index d0a82e4176a..4c237673181 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -997,10 +997,6 @@ const int Matcher::float_pressure(int default_pressure_threshold) { return default_pressure_threshold; } -int Matcher::regnum_to_fpu_offset(int regnum) { - return regnum - 32; // The FP registers are in the second chunk -} - // Vector width in bytes const int Matcher::vector_width_in_bytes(BasicType bt) { return MaxVectorSize; @@ -1664,13 +1660,10 @@ encode %{ // the region from SP to FP meets the minimum stack alignment. frame %{ - // What direction does stack grow in (assumed to be same for native & Java) - stack_direction(TOWARDS_LOW); - // These two registers define part of the calling convention // between compiled code and the interpreter. inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C - interpreter_method_oop_reg(R_Rmethod); // Method Oop Register when calling interpreter + interpreter_method_reg(R_Rmethod); // Method Register when calling interpreter // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] cisc_spilling_operand_name(indOffset); @@ -2530,7 +2523,7 @@ operand inline_cache_regP(iRegP reg) %{ interface(REG_INTER); %} -operand interpreter_method_oop_regP(iRegP reg) %{ +operand interpreter_method_regP(iRegP reg) %{ constraint(ALLOC_IN_RC(Rmethod_regP)); match(reg); format %{ %} diff --git a/src/hotspot/cpu/arm/arm_32.ad b/src/hotspot/cpu/arm/arm_32.ad index 1767f69a287..177c1a7cae0 100644 --- a/src/hotspot/cpu/arm/arm_32.ad +++ b/src/hotspot/cpu/arm/arm_32.ad @@ -196,7 +196,7 @@ alloc_class chunk2(APSR, FPSCR); // Several register classes are automatically defined based upon information in // this architecture description. // 1) reg_class inline_cache_reg ( as defined in frame section ) -// 2) reg_class interpreter_method_oop_reg ( as defined in frame section ) +// 2) reg_class interpreter_method_reg ( as defined in frame section ) // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) // diff --git a/src/hotspot/cpu/arm/globals_arm.hpp b/src/hotspot/cpu/arm/globals_arm.hpp index bbc38662a53..7390729430b 100644 --- a/src/hotspot/cpu/arm/globals_arm.hpp +++ b/src/hotspot/cpu/arm/globals_arm.hpp @@ -70,11 +70,12 @@ define_pd_global(bool, CompactStrings, false); define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); -#define ARCH_FLAGS(develop, \ - product, \ - diagnostic, \ - experimental, \ - notproduct, \ - range, \ +#define ARCH_FLAGS(develop, \ + product, \ + notproduct, \ + range, \ constraint) + +// end of ARCH_FLAGS + #endif // CPU_ARM_GLOBALS_ARM_HPP diff --git a/src/hotspot/cpu/arm/vm_version_arm_32.cpp b/src/hotspot/cpu/arm/vm_version_arm_32.cpp index 6837187d2d5..5331a20f2fe 100644 --- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp +++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp @@ -27,6 +27,7 @@ #include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/os.inline.hpp" #include "runtime/stubCodeGenerator.hpp" diff --git a/src/hotspot/cpu/ppc/c2_init_ppc.cpp b/src/hotspot/cpu/ppc/c2_init_ppc.cpp index fdf4062728c..34b330fee2b 100644 --- a/src/hotspot/cpu/ppc/c2_init_ppc.cpp +++ b/src/hotspot/cpu/ppc/c2_init_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "opto/compile.hpp" #include "opto/node.hpp" #include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" #include "utilities/debug.hpp" // Processor dependent initialization of C2 compiler for ppc. @@ -40,12 +41,6 @@ void Compile::pd_compiler2_init() { } } - if (PowerArchitecturePPC64 == 6) { - if (FLAG_IS_DEFAULT(InsertEndGroupPPC64)) { - FLAG_SET_ERGO(InsertEndGroupPPC64, true); - } - } - if (!VM_Version::has_isel() && FLAG_IS_DEFAULT(ConditionalMoveLimit)) { FLAG_SET_ERGO(ConditionalMoveLimit, 0); } diff --git a/src/hotspot/cpu/ppc/globals_ppc.hpp b/src/hotspot/cpu/ppc/globals_ppc.hpp index 0d546b329df..ccc3ffaa9f2 100644 --- a/src/hotspot/cpu/ppc/globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/globals_ppc.hpp @@ -75,13 +75,11 @@ define_pd_global(bool, CompactStrings, true); define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); // Platform dependent flag handling: flags only defined on this platform. -#define ARCH_FLAGS(develop, \ - product, \ - diagnostic, \ - experimental, \ - notproduct, \ - range, \ - constraint) \ +#define ARCH_FLAGS(develop, \ + product, \ + notproduct, \ + range, \ + constraint) \ \ product(uintx, PowerArchitecturePPC64, 0, \ "Specify the PowerPC family version in use. If not provided, " \ @@ -136,12 +134,6 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); product(bool, UseStaticBranchPredictionForUncommonPathsPPC64, false, \ "Use static branch prediction hints for uncommon paths.") \ \ - product(bool, UsePower6SchedulerPPC64, false, \ - "Use Power6 Scheduler.") \ - \ - product(bool, InsertEndGroupPPC64, false, \ - "Insert EndGroup instructions to optimize for Power6.") \ - \ /* Trap based checks. */ \ /* Trap based checks use the ppc trap instructions to check certain */ \ /* conditions. This instruction raises a SIGTRAP caught by the */ \ @@ -161,7 +153,7 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); product(bool, UseRTMLocking, false, \ "Enable RTM lock eliding for inflated locks in compiled code") \ \ - experimental(bool, UseRTMForStackLocks, false, \ + product(bool, UseRTMForStackLocks, false, EXPERIMENTAL, \ "Enable RTM lock eliding for stack locks in compiled code") \ \ product(bool, UseRTMDeopt, false, \ @@ -171,33 +163,35 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); "Number of RTM retries on lock abort or busy") \ range(0, max_jint) \ \ - experimental(int, RTMSpinLoopCount, 100, \ + product(int, RTMSpinLoopCount, 100, EXPERIMENTAL, \ "Spin count for lock to become free before RTM retry") \ range(0, 32767) /* immediate operand limit on ppc */ \ \ - experimental(int, RTMAbortThreshold, 1000, \ + product(int, RTMAbortThreshold, 1000, EXPERIMENTAL, \ "Calculate abort ratio after this number of aborts") \ range(0, max_jint) \ \ - experimental(int, RTMLockingThreshold, 10000, \ + product(int, RTMLockingThreshold, 10000, EXPERIMENTAL, \ "Lock count at which to do RTM lock eliding without " \ "abort ratio calculation") \ range(0, max_jint) \ \ - experimental(int, RTMAbortRatio, 50, \ + product(int, RTMAbortRatio, 50, EXPERIMENTAL, \ "Lock abort ratio at which to stop use RTM lock eliding") \ range(0, 100) /* natural range */ \ \ - experimental(int, RTMTotalCountIncrRate, 64, \ + product(int, RTMTotalCountIncrRate, 64, EXPERIMENTAL, \ "Increment total RTM attempted lock count once every n times") \ range(1, 32767) /* immediate operand limit on ppc */ \ constraint(RTMTotalCountIncrRateConstraintFunc,AfterErgo) \ \ - experimental(intx, RTMLockingCalculationDelay, 0, \ + product(intx, RTMLockingCalculationDelay, 0, EXPERIMENTAL, \ "Number of milliseconds to wait before start calculating aborts " \ "for RTM locking") \ \ - experimental(bool, UseRTMXendForLockBusy, true, \ - "Use RTM Xend instead of Xabort when lock busy") \ + product(bool, UseRTMXendForLockBusy, true, EXPERIMENTAL, \ + "Use RTM Xend instead of Xabort when lock busy") + +// end of ARCH_FLAGS #endif // CPU_PPC_GLOBALS_PPC_HPP diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 0258118af9b..e504b0ce62c 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -535,8 +535,8 @@ alloc_class chunk4 ( // information in this architecture description. // 1) reg_class inline_cache_reg ( as defined in frame section ) -// 2) reg_class compiler_method_oop_reg ( as defined in frame section ) -// 2) reg_class interpreter_method_oop_reg ( as defined in frame section ) +// 2) reg_class compiler_method_reg ( as defined in frame section ) +// 2) reg_class interpreter_method_reg ( as defined in frame section ) // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) // @@ -1370,31 +1370,6 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { } #endif -// Macro used instead of the common __ to emulate the pipes of PPC. -// Instead of e.g. __ ld(...) one hase to write ___(ld) ld(...) This enables the -// micro scheduler to cope with "hand written" assembler like in the prolog. Though -// still no scheduling of this code is possible, the micro scheduler is aware of the -// code and can update its internal data. The following mechanism is used to achieve this: -// The micro scheduler calls size() of each compound node during scheduling. size() does a -// dummy emit and only during this dummy emit C->hb_scheduling() is not NULL. -#if 0 // TODO: PPC port -#define ___(op) if (UsePower6SchedulerPPC64 && C->hb_scheduling()) \ - C->hb_scheduling()->_pdScheduling->PdEmulatePipe(ppc64Opcode_##op); \ - _masm. -#define ___stop if (UsePower6SchedulerPPC64 && C->hb_scheduling()) \ - C->hb_scheduling()->_pdScheduling->PdEmulatePipe(archOpcode_none) -#define ___advance if (UsePower6SchedulerPPC64 && C->hb_scheduling()) \ - C->hb_scheduling()->_pdScheduling->advance_offset -#else -#define ___(op) if (UsePower6SchedulerPPC64) \ - Unimplemented(); \ - _masm. -#define ___stop if (UsePower6SchedulerPPC64) \ - Unimplemented() -#define ___advance if (UsePower6SchedulerPPC64) \ - Unimplemented() -#endif - void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Compile* C = ra_->C; C2_MacroAssembler _masm(&cbuf); @@ -1414,10 +1389,10 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { // Add nop at beginning of all frameless methods to prevent any // oop instructions from getting overwritten by make_not_entrant // (patching attempt would fail). - ___(nop) nop(); + __ nop(); } else { // Get return pc. - ___(mflr) mflr(return_pc); + __ mflr(return_pc); } if (C->clinit_barrier_on_entry()) { @@ -1477,9 +1452,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { if (Assembler::is_simm(stdoffset, 16)) { // Signed 16 bit offset, a simple std is ok. if (UseLoadInstructionsForStackBangingPPC64) { - ___(ld) ld(R0, (int)(signed short)stdoffset, R1_SP); + __ ld(R0, (int)(signed short)stdoffset, R1_SP); } else { - ___(std) std(R0, (int)(signed short)stdoffset, R1_SP); + __ std(R0, (int)(signed short)stdoffset, R1_SP); } } else if (Assembler::is_simm(stdoffset, 31)) { // Use largeoffset calculations for addis & ld/std. @@ -1487,11 +1462,11 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { const int lo = MacroAssembler::largeoffset_si16_si16_lo(stdoffset); Register tmp = R11; - ___(addis) addis(tmp, R1_SP, hi); + __ addis(tmp, R1_SP, hi); if (UseLoadInstructionsForStackBangingPPC64) { - ___(ld) ld(R0, lo, tmp); + __ ld(R0, lo, tmp); } else { - ___(std) std(R0, lo, tmp); + __ std(R0, lo, tmp); } } else { ShouldNotReachHere(); @@ -1506,19 +1481,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { long offset = Assembler::align_addr(bytes, frame::alignment_in_bytes); ciMethod *currMethod = C->method(); - // Optimized version for most common case. - if (UsePower6SchedulerPPC64 && - !method_is_frameless && Assembler::is_simm((int)(-offset), 16) && - !(false /* ConstantsALot TODO: PPC port*/)) { - ___(or) mr(callers_sp, R1_SP); - ___(std) std(return_pc, _abi(lr), R1_SP); - ___(stdu) stdu(R1_SP, -offset, R1_SP); - return; - } - if (!method_is_frameless) { // Get callers sp. - ___(or) mr(callers_sp, R1_SP); + __ mr(callers_sp, R1_SP); // Push method's frame, modifies SP. assert(Assembler::is_uimm(framesize, 32U), "wrong type"); @@ -1527,17 +1492,17 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Register tmp = push_frame_temp; // Had to insert code of push_frame((unsigned int)framesize, push_frame_temp). if (Assembler::is_simm(-offset, 16)) { - ___(stdu) stdu(R1_SP, -offset, R1_SP); + __ stdu(R1_SP, -offset, R1_SP); } else { long x = -offset; // Had to insert load_const(tmp, -offset). - ___(addis) lis( tmp, (int)((signed short)(((x >> 32) & 0xffff0000) >> 16))); - ___(ori) ori( tmp, tmp, ((x >> 32) & 0x0000ffff)); - ___(rldicr) sldi(tmp, tmp, 32); - ___(oris) oris(tmp, tmp, (x & 0xffff0000) >> 16); - ___(ori) ori( tmp, tmp, (x & 0x0000ffff)); + __ lis( tmp, (int)((signed short)(((x >> 32) & 0xffff0000) >> 16))); + __ ori( tmp, tmp, ((x >> 32) & 0x0000ffff)); + __ sldi(tmp, tmp, 32); + __ oris(tmp, tmp, (x & 0xffff0000) >> 16); + __ ori( tmp, tmp, (x & 0x0000ffff)); - ___(stdux) stdux(R1_SP, R1_SP, tmp); + __ stdux(R1_SP, R1_SP, tmp); } } #if 0 // TODO: PPC port @@ -1552,14 +1517,11 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { #endif if (!method_is_frameless) { // Save return pc. - ___(std) std(return_pc, _abi(lr), callers_sp); + __ std(return_pc, _abi(lr), callers_sp); } C->output()->set_frame_complete(cbuf.insts_size()); } -#undef ___ -#undef ___stop -#undef ___advance uint MachPrologNode::size(PhaseRegAlloc *ra_) const { // Variable size. determine dynamically. @@ -1641,35 +1603,6 @@ const Pipeline * MachEpilogNode::pipeline() const { return MachNode::pipeline_class(); } -#if 0 // TODO: PPC port -void MachLoadPollAddrLateNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { - C2_MacroAssembler _masm(&cbuf); - if (LoadPollAddressFromThread) { - _masm.ld(R11, in_bytes(JavaThread::poll_address_offset()), R16_thread); - } else { - _masm.nop(); - } -} - -uint MachLoadPollAddrLateNode::size(PhaseRegAlloc* ra_) const { - if (LoadPollAddressFromThread) { - return 4; - } else { - return 4; - } -} - -#ifndef PRODUCT -void MachLoadPollAddrLateNode::format(PhaseRegAlloc* ra_, outputStream* st) const { - st->print_cr(" LD R11, PollAddressOffset, R16_thread \t// LoadPollAddressFromThread"); -} -#endif - -const RegMask &MachLoadPollAddrLateNode::out_RegMask() const { - return RSCRATCH1_BITS64_REG_mask(); -} -#endif // PPC port - // ============================================================================= // Figure out which register class each belongs in: rc_int, rc_float, rc_vs or @@ -1952,102 +1885,6 @@ uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { return implementation(NULL, ra_, true, NULL); } -#if 0 // TODO: PPC port -ArchOpcode MachSpillCopyNode_archOpcode(MachSpillCopyNode *n, PhaseRegAlloc *ra_) { -#ifndef PRODUCT - if (ra_->node_regs_max_index() == 0) return archOpcode_undefined; -#endif - assert(ra_->node_regs_max_index() != 0, ""); - - // Get registers to move. - OptoReg::Name src_hi = ra_->get_reg_second(n->in(1)); - OptoReg::Name src_lo = ra_->get_reg_first(n->in(1)); - OptoReg::Name dst_hi = ra_->get_reg_second(n); - OptoReg::Name dst_lo = ra_->get_reg_first(n); - - enum RC src_lo_rc = rc_class(src_lo); - enum RC dst_lo_rc = rc_class(dst_lo); - - if (src_lo == dst_lo && src_hi == dst_hi) - return ppc64Opcode_none; // Self copy, no move. - - // -------------------------------------- - // Memory->Memory Spill. Use R0 to hold the value. - if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { - return ppc64Opcode_compound; - } - - // -------------------------------------- - // Check for float->int copy; requires a trip through memory. - if (src_lo_rc == rc_float && dst_lo_rc == rc_int) { - Unimplemented(); - } - - // -------------------------------------- - // Check for integer reg-reg copy. - if (src_lo_rc == rc_int && dst_lo_rc == rc_int) { - Register Rsrc = as_Register(Matcher::_regEncode[src_lo]); - Register Rdst = as_Register(Matcher::_regEncode[dst_lo]); - if (Rsrc == Rdst) { - return ppc64Opcode_none; - } else { - return ppc64Opcode_or; - } - } - - // Check for integer store. - if (src_lo_rc == rc_int && dst_lo_rc == rc_stack) { - if (src_hi != OptoReg::Bad) { - return ppc64Opcode_std; - } else { - return ppc64Opcode_stw; - } - } - - // Check for integer load. - if (dst_lo_rc == rc_int && src_lo_rc == rc_stack) { - if (src_hi != OptoReg::Bad) { - return ppc64Opcode_ld; - } else { - return ppc64Opcode_lwz; - } - } - - // Check for float reg-reg copy. - if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { - return ppc64Opcode_fmr; - } - - // Check for float store. - if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) { - if (src_hi != OptoReg::Bad) { - return ppc64Opcode_stfd; - } else { - return ppc64Opcode_stfs; - } - } - - // Check for float load. - if (dst_lo_rc == rc_float && src_lo_rc == rc_stack) { - if (src_hi != OptoReg::Bad) { - return ppc64Opcode_lfd; - } else { - return ppc64Opcode_lfs; - } - } - - // -------------------------------------------------------------------- - // Check for hi bits still needing moving. Only happens for misaligned - // arguments to native calls. - if (src_hi == dst_hi) { - return ppc64Opcode_none; // Self copy; no move. - } - - ShouldNotReachHere(); - return ppc64Opcode_undefined; -} -#endif // PPC port - #ifndef PRODUCT void MachNopNode::format(PhaseRegAlloc *ra_, outputStream *st) const { st->print("NOP \t// %d nops to pad for loops.", _count); @@ -2143,13 +1980,6 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { // Argument is valid and klass is as expected, continue. } -#if 0 // TODO: PPC port -// Optimize UEP code on z (save a load_const() call in main path). -int MachUEPNode::ep_offset() { - return 0; -} -#endif - uint MachUEPNode::size(PhaseRegAlloc *ra_) const { // Variable size. Determine dynamically. return MachNode::size(ra_); @@ -2335,12 +2165,6 @@ const int Matcher::float_pressure(int default_pressure_threshold) { return default_pressure_threshold; } -int Matcher::regnum_to_fpu_offset(int regnum) { - // No user for this method? - Unimplemented(); - return 999; -} - const bool Matcher::convL2FSupported(void) { // fcfids can do the conversion (>= Power7). // fcfid + frsp showed rounding problem when result should be 0x3f800001. @@ -2678,23 +2502,19 @@ const bool Matcher::convi2l_type_required = true; // needs for encoding need to be specified. encode %{ enc_class enc_unimplemented %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); __ unimplemented("Unimplemented mach node encoding in AD file.", 13); %} enc_class enc_untested %{ #ifdef ASSERT - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); __ untested("Untested mach node encoding in AD file."); #else - // TODO: PPC port $archOpcode(ppc64Opcode_none); #endif %} enc_class enc_lbz(iRegIdst dst, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lbz); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lbz($dst$$Register, Idisp, $mem$$base$$Register); @@ -2702,7 +2522,6 @@ encode %{ // Load acquire. enc_class enc_lbz_ac(iRegIdst dst, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lbz($dst$$Register, Idisp, $mem$$base$$Register); @@ -2711,7 +2530,6 @@ encode %{ %} enc_class enc_lhz(iRegIdst dst, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lhz); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); @@ -2720,7 +2538,6 @@ encode %{ // Load acquire. enc_class enc_lhz_ac(iRegIdst dst, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); @@ -2730,7 +2547,6 @@ encode %{ %} enc_class enc_lwz(iRegIdst dst, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lwz); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); @@ -2739,7 +2555,6 @@ encode %{ // Load acquire. enc_class enc_lwz_ac(iRegIdst dst, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); @@ -2749,7 +2564,6 @@ encode %{ %} enc_class enc_ld(iRegLdst dst, memoryAlg4 mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ld); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); // Operand 'ds' requires 4-alignment. @@ -2759,7 +2573,6 @@ encode %{ // Load acquire. enc_class enc_ld_ac(iRegLdst dst, memoryAlg4 mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); // Operand 'ds' requires 4-alignment. @@ -2770,14 +2583,12 @@ encode %{ %} enc_class enc_lfd(RegF dst, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lfd); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lfd($dst$$FloatRegister, Idisp, $mem$$base$$Register); %} enc_class enc_load_long_constL(iRegLdst dst, immL src, iRegLdst toc) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ld); C2_MacroAssembler _masm(&cbuf); int toc_offset = 0; @@ -2801,7 +2612,6 @@ encode %{ %} enc_class enc_load_long_constL_hi(iRegLdst dst, iRegLdst toc, immL src) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); C2_MacroAssembler _masm(&cbuf); @@ -3036,7 +2846,6 @@ encode %{ %} enc_class enc_load_long_constP(iRegLdst dst, immP src, iRegLdst toc) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ld); C2_MacroAssembler _masm(&cbuf); int toc_offset = 0; @@ -3069,7 +2878,6 @@ encode %{ %} enc_class enc_load_long_constP_hi(iRegLdst dst, immP src, iRegLdst toc) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); C2_MacroAssembler _masm(&cbuf); if (!ra_->C->output()->in_scratch_emit_size()) { @@ -3204,14 +3012,12 @@ encode %{ %} enc_class enc_stw(iRegIsrc src, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_stw); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ stw($src$$Register, Idisp, $mem$$base$$Register); %} enc_class enc_std(iRegIsrc src, memoryAlg4 mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_std); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); // Operand 'ds' requires 4-alignment. @@ -3220,14 +3026,12 @@ encode %{ %} enc_class enc_stfs(RegF src, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_stfs); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ stfs($src$$FloatRegister, Idisp, $mem$$base$$Register); %} enc_class enc_stfd(RegF src, memory mem) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_stfd); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ stfd($src$$FloatRegister, Idisp, $mem$$base$$Register); @@ -3236,7 +3040,6 @@ encode %{ // Use release_store for card-marking to ensure that previous // oop-stores are visible before the card-mark change. enc_class enc_cms_card_mark(memory mem, iRegLdst releaseFieldAddr, flagsReg crx) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // FIXME: Implement this as a cmove and use a fixed condition code // register which is written on every transition to compiled code, // e.g. in call-stub and when returning from runtime stubs. @@ -3252,18 +3055,8 @@ encode %{ C2_MacroAssembler _masm(&cbuf); Label skip_storestore; -#if 0 // TODO: PPC port - // Check CMSCollectorCardTableBarrierSetBSExt::_requires_release and do the - // StoreStore barrier conditionally. - __ lwz(R0, 0, $releaseFieldAddr$$Register); - __ cmpwi($crx$$CondRegister, R0, 0); - __ beq_predict_taken($crx$$CondRegister, skip_storestore); -#endif __ li(R0, 0); __ membar(Assembler::StoreStore); -#if 0 // TODO: PPC port - __ bind(skip_storestore); -#endif // Do the store. if ($mem$$index == 0) { @@ -3468,7 +3261,6 @@ encode %{ %} enc_class enc_cmove_reg(iRegIdst dst, flagsRegSrc crx, iRegIsrc src, cmpOp cmp) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmove); C2_MacroAssembler _masm(&cbuf); int cc = $cmp$$cmpcode; @@ -3478,12 +3270,10 @@ encode %{ // Branch if not (cmp crx). __ bc(cc_to_inverse_boint(cc), cc_to_biint(cc, flags_reg), done); __ mr($dst$$Register, $src$$Register); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} enc_class enc_cmove_imm(iRegIdst dst, flagsRegSrc crx, immI16 src, cmpOp cmp) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmove); C2_MacroAssembler _masm(&cbuf); Label done; @@ -3491,20 +3281,17 @@ encode %{ // Branch if not (cmp crx). __ bc(cc_to_inverse_boint($cmp$$cmpcode), cc_to_biint($cmp$$cmpcode, $crx$$reg), done); __ li($dst$$Register, $src$$constant); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} // This enc_class is needed so that scheduler gets proper // input mapping for latency computation. enc_class enc_andc(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_andc); C2_MacroAssembler _masm(&cbuf); __ andc($dst$$Register, $src1$$Register, $src2$$Register); %} enc_class enc_convI2B_regI__cmove(iRegIdst dst, iRegIsrc src, flagsReg crx, immI16 zero, immI16 notzero) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); @@ -3517,7 +3304,6 @@ encode %{ %} enc_class enc_convP2B_regP__cmove(iRegIdst dst, iRegPsrc src, flagsReg crx, immI16 zero, immI16 notzero) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); @@ -3530,30 +3316,25 @@ encode %{ %} enc_class enc_cmove_bso_stackSlotL(iRegLdst dst, flagsRegSrc crx, stackSlotL mem ) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmove); C2_MacroAssembler _masm(&cbuf); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); Label done; __ bso($crx$$CondRegister, done); __ ld($dst$$Register, Idisp, $mem$$base$$Register); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} enc_class enc_cmove_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmove); C2_MacroAssembler _masm(&cbuf); Label done; __ bso($crx$$CondRegister, done); __ mffprd($dst$$Register, $src$$FloatRegister); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} enc_class enc_bc(flagsRegSrc crx, cmpOp cmp, Label lbl) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_bc); C2_MacroAssembler _masm(&cbuf); Label d; // dummy @@ -3583,7 +3364,6 @@ encode %{ enc_class enc_bc_far(flagsRegSrc crx, cmpOp cmp, Label lbl) %{ // The scheduler doesn't know about branch shortening, so we set the opcode // to ppc64Opcode_bc in order to hide this detail from the scheduler. - // TODO: PPC port $archOpcode(ppc64Opcode_bc); C2_MacroAssembler _masm(&cbuf); Label d; // dummy @@ -3611,47 +3391,6 @@ encode %{ MacroAssembler::bc_far_optimize_on_relocate); %} - // Branch used with Power6 scheduling (can be shortened without changing the node). - enc_class enc_bc_short_far(flagsRegSrc crx, cmpOp cmp, Label lbl) %{ - // The scheduler doesn't know about branch shortening, so we set the opcode - // to ppc64Opcode_bc in order to hide this detail from the scheduler. - // TODO: PPC port $archOpcode(ppc64Opcode_bc); - - C2_MacroAssembler _masm(&cbuf); - Label d; // dummy - __ bind(d); - Label* p = ($lbl$$label); - // `p' is `NULL' when this encoding class is used only to - // determine the size of the encoded instruction. - Label& l = (NULL == p)? d : *(p); - int cc = $cmp$$cmpcode; - int flags_reg = $crx$$reg; - int bhint = Assembler::bhintNoHint; - - if (UseStaticBranchPredictionForUncommonPathsPPC64) { - if (_prob <= PROB_NEVER) { - bhint = Assembler::bhintIsNotTaken; - } else if (_prob >= PROB_ALWAYS) { - bhint = Assembler::bhintIsTaken; - } - } - -#if 0 // TODO: PPC port - if (_size == 8) { - // Tell the conditional far branch to optimize itself when being relocated. - __ bc_far(Assembler::add_bhint_to_boint(bhint, cc_to_boint(cc)), - cc_to_biint(cc, flags_reg), - l, - MacroAssembler::bc_far_optimize_on_relocate); - } else { - __ bc (Assembler::add_bhint_to_boint(bhint, cc_to_boint(cc)), - cc_to_biint(cc, flags_reg), - l); - } -#endif - Unimplemented(); - %} - // Postalloc expand emitter for loading a replicatef float constant from // the method's TOC. // Enc_class needed as consttanttablebase is not supported by postalloc @@ -3698,7 +3437,6 @@ encode %{ // This enc_class is needed so that scheduler gets proper // input mapping for latency computation. enc_class enc_poll(immI dst, iRegLdst poll) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ld); // Fake operand dst needed for PPC scheduler. assert($dst$$constant == 0x0, "dst must be 0x0"); @@ -3756,7 +3494,6 @@ encode %{ // // Usage of r1 and r2 in the stubs allows to distinguish them. enc_class enc_java_static_call(method meth) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_bl); C2_MacroAssembler _masm(&cbuf); address entry_point = (address)$meth$$method; @@ -3806,7 +3543,6 @@ encode %{ // Second node of expanded dynamic call - the call. enc_class enc_java_dynamic_call_sched(method meth) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_bl); C2_MacroAssembler _masm(&cbuf); @@ -3863,7 +3599,6 @@ encode %{ call->_tf = _tf; call->_entry_point = _entry_point; call->_cnt = _cnt; - call->_argsize = _argsize; call->_oop_map = _oop_map; call->_jvms = _jvms; call->_jvmadj = _jvmadj; @@ -3910,7 +3645,6 @@ encode %{ // Toc is only passed so that it can be used in ins_encode statement. // In the code we have to use $constanttablebase. enc_class enc_java_dynamic_call(method meth, iRegLdst toc) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); int start_offset = __ offset(); @@ -3968,7 +3702,6 @@ encode %{ // a runtime call enc_class enc_java_to_runtime_call (method meth) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); C2_MacroAssembler _masm(&cbuf); const address start_pc = __ pc(); @@ -4002,7 +3735,6 @@ encode %{ // This enc_class is needed so that scheduler gets proper // input mapping for latency computation. enc_class enc_leaf_call_mtctr(iRegLsrc src) %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mtctr); C2_MacroAssembler _masm(&cbuf); __ mtctr($src$$Register); %} @@ -4067,7 +3799,6 @@ encode %{ call->_tf = _tf; call->_entry_point = _entry_point; call->_cnt = _cnt; - call->_argsize = _argsize; call->_oop_map = _oop_map; guarantee(!_jvms, "You must clone the jvms and adapt the offsets by fix_jvms()."); call->_jvms = NULL; @@ -4118,17 +3849,14 @@ encode %{ // Definition of frame structure and management information. frame %{ - // What direction does stack grow in (assumed to be same for native & Java). - stack_direction(TOWARDS_LOW); - // These two registers define part of the calling convention between // compiled code and the interpreter. // Inline Cache Register or method for I2C. inline_cache_reg(R19); // R19_method - // Method Oop Register when calling interpreter. - interpreter_method_oop_reg(R19); // R19_method + // Method Register when calling interpreter. + interpreter_method_reg(R19); // R19_method // Optional: name the operand used by cisc-spilling to access // [stack_pointer + offset]. @@ -5037,15 +4765,15 @@ operand inline_cache_regP(iRegPdst reg) %{ interface(REG_INTER); %} -operand compiler_method_oop_regP(iRegPdst reg) %{ - constraint(ALLOC_IN_RC(rscratch1_bits64_reg)); // compiler_method_oop_reg +operand compiler_method_regP(iRegPdst reg) %{ + constraint(ALLOC_IN_RC(rscratch1_bits64_reg)); // compiler_method_reg match(reg); format %{ %} interface(REG_INTER); %} -operand interpreter_method_oop_regP(iRegPdst reg) %{ - constraint(ALLOC_IN_RC(r19_bits64_reg)); // interpreter_method_oop_reg +operand interpreter_method_regP(iRegPdst reg) %{ + constraint(ALLOC_IN_RC(r19_bits64_reg)); // interpreter_method_reg match(reg); format %{ %} interface(REG_INTER); @@ -5514,7 +5242,6 @@ instruct convB2I_reg_2(iRegIdst dst, iRegIsrc src) %{ format %{ "EXTSB $dst, $src \t// byte->int" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_extsb); __ extsb($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -5672,7 +5399,6 @@ instruct loadS(iRegIdst dst, memory mem) %{ format %{ "LHA $dst, $mem" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lha); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lha($dst$$Register, Idisp, $mem$$base$$Register); %} @@ -5689,7 +5415,6 @@ instruct loadS_ac(iRegIdst dst, memory mem) %{ "ISYNC" %} size(12); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lha($dst$$Register, Idisp, $mem$$base$$Register); __ twi_0($dst$$Register); @@ -5796,7 +5521,6 @@ instruct loadI2L(iRegLdst dst, memoryAlg4 mem) %{ format %{ "LWA $dst, $mem \t// loadI2L" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lwa); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lwa($dst$$Register, Idisp, $mem$$base$$Register); %} @@ -5813,7 +5537,6 @@ instruct loadI2L_ac(iRegLdst dst, memoryAlg4 mem) %{ "ISYNC" %} size(12); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lwa); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lwa($dst$$Register, Idisp, $mem$$base$$Register); __ twi_0($dst$$Register); @@ -6015,7 +5738,6 @@ instruct loadF(regF dst, memory mem) %{ format %{ "LFS $dst, $mem" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lfs); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ lfs($dst$$FloatRegister, Idisp, $mem$$base$$Register); %} @@ -6035,7 +5757,6 @@ instruct loadF_ac(regF dst, memory mem, flagsRegCR0 cr0) %{ "ISYNC" %} size(16); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); Label next; __ lfs($dst$$FloatRegister, Idisp, $mem$$base$$Register); @@ -6072,7 +5793,6 @@ instruct loadD_ac(regD dst, memory mem, flagsRegCR0 cr0) %{ "ISYNC" %} size(16); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); Label next; __ lfd($dst$$FloatRegister, Idisp, $mem$$base$$Register); @@ -6107,7 +5827,6 @@ instruct loadToc_hi(iRegLdst dst) %{ format %{ "ADDIS $dst, R29, DISP.hi \t// load TOC hi" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); __ calculate_address_from_global_toc_hi16only($dst$$Register, __ method_toc()); %} ins_pipe(pipe_class_default); @@ -6121,7 +5840,6 @@ instruct loadToc_lo(iRegLdst dst, iRegLdst src) %{ format %{ "ADDI $dst, $src, DISP.lo \t// load TOC lo" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ori); __ calculate_address_from_global_toc_lo16only($dst$$Register, __ method_toc()); %} ins_pipe(pipe_class_default); @@ -6134,7 +5852,6 @@ instruct loadConI16(iRegIdst dst, immI16 src) %{ format %{ "LI $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($src$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -6148,7 +5865,6 @@ instruct loadConIhi16(iRegIdst dst, immIhi16 src) %{ format %{ "LIS $dst, $src.hi" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); // Lis sign extends 16-bit src then shifts it 16 bit to the left. __ lis($dst$$Register, (int)((short)(($src$$constant & 0xFFFF0000) >> 16))); %} @@ -6165,7 +5881,6 @@ instruct loadConI32_lo16(iRegIdst dst, iRegIsrc src1, immI16 src2) %{ format %{ "ORI $dst, $src1.hi, $src2.lo" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ori); __ ori($dst$$Register, $src1$$Register, ($src2$$constant) & 0xFFFF); %} ins_pipe(pipe_class_default); @@ -6193,7 +5908,6 @@ instruct loadConL16(iRegLdst dst, immL16 src) %{ format %{ "LI $dst, $src \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short) ($src$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -6207,7 +5921,6 @@ instruct loadConL32hi16(iRegLdst dst, immL32hi16 src) %{ format %{ "LIS $dst, $src.hi \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); __ lis($dst$$Register, (int)((short)(($src$$constant & 0xFFFF0000) >> 16))); %} ins_pipe(pipe_class_default); @@ -6223,7 +5936,6 @@ instruct loadConL32_lo16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ format %{ "ORI $dst, $src1, $src2.lo" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ori); __ ori($dst$$Register, $src1$$Register, ($src2$$constant) & 0xFFFF); %} ins_pipe(pipe_class_default); @@ -6303,7 +6015,6 @@ instruct loadConL_lo(iRegLdst dst, immL src, iRegLdst base) %{ format %{ "LD $dst, offset, $base \t// load long $src from TOC (lo)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ld); int offset = ra_->C->output()->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset; __ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register); %} @@ -6330,7 +6041,6 @@ instruct loadConN0(iRegNdst dst, immN_0 src) %{ format %{ "LI $dst, $src \t// compressed ptr" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, 0); %} ins_pipe(pipe_class_default); @@ -6344,7 +6054,6 @@ instruct loadConN_hi(iRegNdst dst, immN src) %{ format %{ "LIS $dst, $src \t// narrow oop hi" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); __ lis($dst$$Register, (int)(short)(($src$$constant >> 16) & 0xffff)); %} ins_pipe(pipe_class_default); @@ -6358,7 +6067,6 @@ instruct loadConN_lo(iRegNdst dst, iRegNsrc src1, immN src2) %{ format %{ "ORI $dst, $src1, $src2 \t// narrow oop lo" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); assert(__ oop_recorder() != NULL, "this assembler needs an OopRecorder"); int oop_index = __ oop_recorder()->find_index((jobject)$src2$$constant); RelocationHolder rspec = oop_Relocation::spec(oop_index); @@ -6389,7 +6097,6 @@ instruct clearMs32b(iRegNdst dst, iRegNsrc src) %{ format %{ "MASK $dst, $src, 0xFFFFFFFF" %} // mask size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src$$Register, 0x20); %} ins_pipe(pipe_class_default); @@ -6402,7 +6109,6 @@ instruct loadBase(iRegLdst dst) %{ format %{ "LoadConst $dst, heapbase" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ load_const_optimized($dst$$Register, CompressedOops::base(), R0); %} ins_pipe(pipe_class_default); @@ -6450,7 +6156,6 @@ instruct loadConNKlass_hi(iRegNdst dst, immNKlass_NM src) %{ format %{ "LIS $dst, $src \t// narrow klass hi" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); intptr_t Csrc = CompressedKlassPointers::encode((Klass *)$src$$constant); __ lis($dst$$Register, (int)(short)((Csrc >> 16) & 0xffff)); %} @@ -6466,7 +6171,6 @@ instruct loadConNKlass_mask(iRegNdst dst, immNKlass_NM src1, iRegNsrc src2) %{ format %{ "MASK $dst, $src2, 0xFFFFFFFF" %} // mask size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src2$$Register, 0x20); %} ins_pipe(pipe_class_default); @@ -6482,7 +6186,6 @@ instruct loadConNKlass_lo(iRegNdst dst, immNKlass_NM src1, iRegNsrc src2) %{ format %{ "ORI $dst, $src1, $src2 \t// narrow klass lo" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ori); intptr_t Csrc = CompressedKlassPointers::encode((Klass *)$src1$$constant); assert(__ oop_recorder() != NULL, "this assembler needs an OopRecorder"); int klass_index = __ oop_recorder()->find_index((Klass *)$src1$$constant); @@ -6540,7 +6243,6 @@ instruct loadConP0or1(iRegPdst dst, immP_0or1 src) %{ format %{ "LI $dst, $src \t// ptr" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($src$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -6588,7 +6290,6 @@ instruct loadConP_lo(iRegPdst dst, immP_NM src, iRegLdst base) %{ format %{ "LD $dst, offset, $base \t// load ptr $src from TOC (lo)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ld); int offset = ra_->C->output()->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset; __ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register); %} @@ -6625,7 +6326,6 @@ instruct loadConF(regF dst, immF src, iRegLdst toc) %{ format %{ "LFS $dst, offset, $toc \t// load float $src from TOC" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lfs); address float_address = __ float_constant($src$$constant); if (float_address == NULL) { ciEnv::current()->record_out_of_memory_failure(); @@ -6648,7 +6348,6 @@ instruct loadConFComp(regF dst, immF src, iRegLdst toc) %{ "ADDIS $toc, $toc, -offset_hi"%} size(12); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); FloatRegister Rdst = $dst$$FloatRegister; Register Rtoc = $toc$$Register; address float_address = __ float_constant($src$$constant); @@ -6689,7 +6388,6 @@ instruct loadConD(regD dst, immD src, iRegLdst toc) %{ format %{ "LFD $dst, offset, $toc \t// load double $src from TOC" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lfd); address float_address = __ double_constant($src$$constant); if (float_address == NULL) { ciEnv::current()->record_out_of_memory_failure(); @@ -6713,7 +6411,6 @@ instruct loadConDComp(regD dst, immD src, iRegLdst toc) %{ "ADDIS $toc, $toc, -offset_hi" %} size(12); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); FloatRegister Rdst = $dst$$FloatRegister; Register Rtoc = $toc$$Register; address float_address = __ double_constant($src$$constant); @@ -6756,7 +6453,6 @@ instruct prefetch_alloc_zero(indirectMemory mem, iRegLsrc src) %{ format %{ "PREFETCH $mem, 2, $src \t// Prefetch write-many with zero" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_dcbtst); __ dcbz($src$$Register, $mem$$base$$Register); %} ins_pipe(pipe_class_memory); @@ -6770,7 +6466,6 @@ instruct prefetch_alloc_zero_no_offset(indirectMemory mem) %{ format %{ "PREFETCH $mem, 2 \t// Prefetch write-many with zero" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_dcbtst); __ dcbz($mem$$base$$Register); %} ins_pipe(pipe_class_memory); @@ -6784,7 +6479,6 @@ instruct prefetch_alloc(indirectMemory mem, iRegLsrc src) %{ format %{ "PREFETCH $mem, 2, $src \t// Prefetch write-many" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_dcbtst); __ dcbtst($src$$Register, $mem$$base$$Register); %} ins_pipe(pipe_class_memory); @@ -6798,7 +6492,6 @@ instruct prefetch_alloc_no_offset(indirectMemory mem) %{ format %{ "PREFETCH $mem, 2 \t// Prefetch write-many" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_dcbtst); __ dcbtst($mem$$base$$Register); %} ins_pipe(pipe_class_memory); @@ -6814,7 +6507,6 @@ instruct storeB(memory mem, iRegIsrc src) %{ format %{ "STB $src, $mem \t// byte" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_stb); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ stb($src$$Register, Idisp, $mem$$base$$Register); %} @@ -6829,7 +6521,6 @@ instruct storeC(memory mem, iRegIsrc src) %{ format %{ "STH $src, $mem \t// short" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sth); int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); __ sth($src$$Register, Idisp, $mem$$base$$Register); %} @@ -6983,7 +6674,6 @@ instruct storeCM_G1(memory mem, immI_0 zero) %{ format %{ "STB #0, $mem \t// CMS card-mark byte store (G1)" %} size(8); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ li(R0, 0); //__ release(); // G1: oops are allowed to get visible after dirty marking guarantee($mem$$base$$Register != R1_SP, "use frame_slots_bias"); @@ -7005,7 +6695,6 @@ instruct encodeP_shift(iRegNdst dst, iRegNsrc src) %{ format %{ "SRDI $dst, $src, 3 \t// encode" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ srdi($dst$$Register, $src$$Register, CompressedOops::shift() & 0x3f); %} ins_pipe(pipe_class_default); @@ -7019,7 +6708,6 @@ instruct encodeP_sub(iRegPdst dst, iRegPdst src) %{ format %{ "SUB $dst, $src, oop_base \t// encode" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ sub_const_optimized($dst$$Register, $src$$Register, CompressedOops::base(), R0); %} ins_pipe(pipe_class_default); @@ -7035,7 +6723,6 @@ instruct cond_sub_base(iRegNdst dst, flagsRegSrc crx, iRegPsrc src1) %{ "SUB $dst, $src1, heapbase \t// encode: subtract base if != NULL\n" "done:" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Label done; __ beq($crx$$CondRegister, done); __ sub_const_optimized($dst$$Register, $src1$$Register, CompressedOops::base(), R0); @@ -7054,7 +6741,6 @@ instruct cond_set_0_oop(iRegNdst dst, flagsRegSrc crx, iRegPsrc src1) %{ size(4); ins_encode %{ // This is a Power7 instruction for which no machine description exists. - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ isel_0($dst$$Register, $crx$$CondRegister, Assembler::equal, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -7068,7 +6754,6 @@ instruct encodeP_Disjoint(iRegNdst dst, iRegPsrc src) %{ format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ rldicl($dst$$Register, $src$$Register, 64-CompressedOops::shift(), 32); %} ins_pipe(pipe_class_default); @@ -7107,7 +6792,6 @@ instruct encodeP_not_null_base_null(iRegNdst dst, iRegPsrc src) %{ format %{ "SRDI $dst, $src, #3 \t// encodeP, $src != NULL" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ srdi($dst$$Register, $src$$Register, CompressedOops::shift() & 0x3f); %} ins_pipe(pipe_class_default); @@ -7122,7 +6806,6 @@ instruct encodeP_narrow_oop_shift_0(iRegNdst dst, iRegPsrc src) %{ format %{ "MR $dst, $src \t// Ptr->Narrow" %} // variable size, 0 or 4. ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ mr_if_needed($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -7139,7 +6822,6 @@ instruct decodeN_shift(iRegPdst dst, iRegPsrc src) %{ format %{ "SLDI $dst, $src, #3 \t// DecodeN" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ sldi($dst$$Register, $src$$Register, CompressedOops::shift()); %} ins_pipe(pipe_class_default); @@ -7153,7 +6835,6 @@ instruct decodeN_add(iRegPdst dst, iRegPdst src) %{ format %{ "ADD $dst, $src, heapbase \t// DecodeN, add oop base" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ add_const_optimized($dst$$Register, $src$$Register, CompressedOops::base(), R0); %} ins_pipe(pipe_class_default); @@ -7172,7 +6853,6 @@ instruct cond_add_base(iRegPdst dst, flagsRegSrc crx, iRegPsrc src) %{ "ADD $dst, $src, heapbase \t// DecodeN: add oop base if $src != NULL\n" "done:" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Label done; __ beq($crx$$CondRegister, done); __ add_const_optimized($dst$$Register, $src$$Register, CompressedOops::base(), R0); @@ -7193,7 +6873,6 @@ instruct cond_set_0_ptr(iRegPdst dst, flagsRegSrc crx, iRegPsrc src1) %{ size(4); ins_encode %{ // This is a Power7 instruction for which no machine description exists. - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ isel_0($dst$$Register, $crx$$CondRegister, Assembler::equal, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -7222,7 +6901,6 @@ instruct decodeN_nullBase(iRegPdst dst, iRegNsrc src) %{ format %{ "SLDI $dst, $src, #3 \t// DecodeN (zerobased)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ sldi($dst$$Register, $src$$Register, CompressedOops::shift()); %} ins_pipe(pipe_class_default); @@ -7239,7 +6917,6 @@ instruct decodeN_mergeDisjoint(iRegPdst dst, iRegNsrc src, iRegLsrc base) %{ format %{ "RLDIMI $dst, $src, shift, 32-shift \t// DecodeN (disjoint base)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldimi); __ rldimi($dst$$Register, $src$$Register, CompressedOops::shift(), 32-CompressedOops::shift()); %} ins_pipe(pipe_class_default); @@ -7350,7 +7027,6 @@ instruct decodeN_unscaled(iRegPdst dst, iRegNsrc src) %{ format %{ "MR $dst, $src \t// DecodeN (unscaled)" %} // variable size, 0 or 4. ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ mr_if_needed($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -7365,7 +7041,6 @@ instruct decodeN2I_unscaled(iRegIdst dst, iRegNsrc src) %{ format %{ "MR $dst, $src \t// (int)DecodeN (unscaled)" %} // variable size, 0 or 4. ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ mr_if_needed($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -7384,7 +7059,6 @@ instruct encodePKlass_shift(iRegNdst dst, iRegNsrc src) %{ format %{ "SRDI $dst, $src, 3 \t// encode" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ srdi($dst$$Register, $src$$Register, CompressedKlassPointers::shift()); %} ins_pipe(pipe_class_default); @@ -7399,7 +7073,6 @@ instruct encodePKlass_sub_base(iRegPdst dst, iRegLsrc base, iRegPdst src) %{ format %{ "SUB $dst, $base, $src \t// encode" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_subf); __ subf($dst$$Register, $base$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -7413,7 +7086,6 @@ instruct encodePKlass_Disjoint(iRegNdst dst, iRegPsrc src) %{ format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ rldicl($dst$$Register, $src$$Register, 64-CompressedKlassPointers::shift(), 32); %} ins_pipe(pipe_class_default); @@ -7473,7 +7145,6 @@ instruct decodeNKlass_shift(iRegPdst dst, iRegPsrc src) %{ format %{ "SLDI $dst, $src, #3 \t// DecodeNKlass" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ sldi($dst$$Register, $src$$Register, CompressedKlassPointers::shift()); %} ins_pipe(pipe_class_default); @@ -7489,7 +7160,6 @@ instruct decodeNKlass_add_base(iRegPdst dst, iRegLsrc base, iRegPdst src) %{ format %{ "ADD $dst, $base, $src \t// DecodeNKlass, add klass base" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_add); __ add($dst$$Register, $base$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -7553,7 +7223,6 @@ instruct membar_acquire() %{ format %{ "MEMBAR-acquire" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lwsync); __ acquire(); %} ins_pipe(pipe_class_default); @@ -7587,7 +7256,6 @@ instruct membar_release() %{ format %{ "MEMBAR-release" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lwsync); __ release(); %} ins_pipe(pipe_class_default); @@ -7600,7 +7268,6 @@ instruct membar_storestore() %{ format %{ "MEMBAR-store-store" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lwsync); __ membar(Assembler::StoreStore); %} ins_pipe(pipe_class_default); @@ -7623,7 +7290,6 @@ instruct membar_volatile() %{ format %{ "MEMBAR-volatile" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sync); __ fence(); %} ins_pipe(pipe_class_default); @@ -7682,7 +7348,6 @@ instruct cmovI_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegIdst dst, iRegIsrc src) ins_encode %{ // This is a Power7 instruction for which no machine description // exists. Anyways, the scheduler should be off on Power7. - // TODO: PPC port $archOpcode(ppc64Opcode_compound); int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -7699,7 +7364,7 @@ instruct cmovI_reg(cmpOp cmp, flagsRegSrc crx, iRegIdst dst, iRegIsrc src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7712,7 +7377,7 @@ instruct cmovI_imm(cmpOp cmp, flagsRegSrc crx, iRegIdst dst, immI16 src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7728,7 +7393,6 @@ instruct cmovL_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegLdst dst, iRegLsrc src) ins_encode %{ // This is a Power7 instruction for which no machine description // exists. Anyways, the scheduler should be off on Power7. - // TODO: PPC port $archOpcode(ppc64Opcode_compound); int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -7745,7 +7409,7 @@ instruct cmovL_reg(cmpOp cmp, flagsRegSrc crx, iRegLdst dst, iRegLsrc src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7758,7 +7422,7 @@ instruct cmovL_imm(cmpOp cmp, flagsRegSrc crx, iRegLdst dst, immL16 src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7774,7 +7438,6 @@ instruct cmovN_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegNdst dst, iRegNsrc src) ins_encode %{ // This is a Power7 instruction for which no machine description // exists. Anyways, the scheduler should be off on Power7. - // TODO: PPC port $archOpcode(ppc64Opcode_compound); int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -7792,7 +7455,7 @@ instruct cmovN_reg(cmpOp cmp, flagsRegSrc crx, iRegNdst dst, iRegNsrc src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7805,7 +7468,7 @@ instruct cmovN_imm(cmpOp cmp, flagsRegSrc crx, iRegNdst dst, immN_0 src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7821,7 +7484,6 @@ instruct cmovP_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegPdst dst, iRegPsrc src) ins_encode %{ // This is a Power7 instruction for which no machine description // exists. Anyways, the scheduler should be off on Power7. - // TODO: PPC port $archOpcode(ppc64Opcode_compound); int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -7838,7 +7500,7 @@ instruct cmovP_reg(cmpOp cmp, flagsRegSrc crx, iRegPdst dst, iRegP_N2P src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7851,7 +7513,7 @@ instruct cmovP_imm(cmpOp cmp, flagsRegSrc crx, iRegPdst dst, immP_0 src) %{ format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); ins_pipe(pipe_class_default); %} @@ -7864,15 +7526,13 @@ instruct cmovF_reg(cmpOp cmp, flagsRegSrc crx, regF dst, regF src) %{ format %{ "CMOVEF $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT (InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8)); + size(8); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmovef); Label done; assert((Assembler::bcondCRbiIs1 & ~Assembler::bcondCRbiIs0) == 8, "check encoding"); // Branch if not (cmp crx). __ bc(cc_to_inverse_boint($cmp$$cmpcode), cc_to_biint($cmp$$cmpcode, $crx$$reg), done); __ fmr($dst$$FloatRegister, $src$$FloatRegister); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} ins_pipe(pipe_class_default); @@ -7886,15 +7546,13 @@ instruct cmovD_reg(cmpOp cmp, flagsRegSrc crx, regD dst, regD src) %{ format %{ "CMOVEF $cmp, $crx, $dst, $src\n\t" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT (InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8)); + size(8); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmovef); Label done; assert((Assembler::bcondCRbiIs1 & ~Assembler::bcondCRbiIs0) == 8, "check encoding"); // Branch if not (cmp crx). __ bc(cc_to_inverse_boint($cmp$$cmpcode), cc_to_biint($cmp$$cmpcode, $crx$$reg), done); __ fmr($dst$$FloatRegister, $src$$FloatRegister); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} ins_pipe(pipe_class_default); @@ -7916,7 +7574,6 @@ instruct storeLConditional_regP_regL_regL(flagsReg crx, indirect mem_ptr, iRegLs effect(TEMP cr0); format %{ "CMPXCHGD if ($crx = ($oldVal == *$mem_ptr)) *mem_ptr = $newVal; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ cmpxchgd($crx$$CondRegister, R0, $oldVal$$Register, $newVal$$Register, $mem_ptr$$Register, MacroAssembler::MemBarAcq, MacroAssembler::cmpxchgx_hint_atomic_update(), noreg, NULL, true); @@ -7936,7 +7593,6 @@ instruct storePConditional_regP_regP_regP(flagsRegCR0 cr0, indirect mem_ptr, iRe format %{ "STDCX_ if ($cr0 = ($oldVal == *$mem_ptr)) *mem_ptr = $newVal; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_stdcx_); __ stdcx_($newVal$$Register, $mem_ptr$$Register); %} ins_pipe(pipe_class_memory); @@ -7952,7 +7608,6 @@ instruct loadPLocked(iRegPdst dst, memory mem) %{ format %{ "LDARX $dst, $mem \t// loadPLocked\n\t" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ldarx); __ ldarx($dst$$Register, $mem$$Register, MacroAssembler::cmpxchgx_hint_atomic_update()); %} ins_pipe(pipe_class_memory); @@ -7972,7 +7627,6 @@ instruct compareAndSwapB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -7992,7 +7646,6 @@ instruct compareAndSwapB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIs effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8012,7 +7665,6 @@ instruct compareAndSwapS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8032,7 +7684,6 @@ instruct compareAndSwapS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIs effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8051,7 +7702,6 @@ instruct compareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8070,7 +7720,6 @@ instruct compareAndSwapN_regP_regN_regN(iRegIdst res, iRegPdst mem_ptr, iRegNsrc effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8089,7 +7738,6 @@ instruct compareAndSwapL_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iRegLsrc effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8108,7 +7756,6 @@ instruct compareAndSwapP_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iRegPsrc effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8130,7 +7777,6 @@ instruct weakCompareAndSwapB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, @@ -8145,7 +7791,6 @@ instruct weakCompareAndSwapB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iR effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, MacroAssembler::MemBarNone, @@ -8160,7 +7805,6 @@ instruct weakCompareAndSwapB_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, @@ -8175,7 +7819,6 @@ instruct weakCompareAndSwapB4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, @@ -8190,7 +7833,6 @@ instruct weakCompareAndSwapS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, @@ -8205,7 +7847,6 @@ instruct weakCompareAndSwapS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iR effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, MacroAssembler::MemBarNone, @@ -8220,7 +7861,6 @@ instruct weakCompareAndSwapS_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, @@ -8235,7 +7875,6 @@ instruct weakCompareAndSwapS4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register, support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter, @@ -8250,7 +7889,6 @@ instruct weakCompareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, @@ -8265,7 +7903,6 @@ instruct weakCompareAndSwapI_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. // Acquire only needed in successful case. Weak node is allowed to report unsuccessful in additional rare cases and // value is never passed to caller. @@ -8282,7 +7919,6 @@ instruct weakCompareAndSwapN_regP_regN_regN(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, @@ -8297,7 +7933,6 @@ instruct weakCompareAndSwapN_acq_regP_regN_regN(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. // Acquire only needed in successful case. Weak node is allowed to report unsuccessful in additional rare cases and // value is never passed to caller. @@ -8314,7 +7949,6 @@ instruct weakCompareAndSwapL_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. // value is never passed to caller. __ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, @@ -8330,7 +7964,6 @@ instruct weakCompareAndSwapL_acq_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as bool" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. // Acquire only needed in successful case. Weak node is allowed to report unsuccessful in additional rare cases and // value is never passed to caller. @@ -8347,7 +7980,6 @@ instruct weakCompareAndSwapP_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, @@ -8362,7 +7994,6 @@ instruct weakCompareAndSwapP_acq_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump format %{ "weak CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as bool; ptr" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. // Acquire only needed in successful case. Weak node is allowed to report unsuccessful in additional rare cases and // value is never passed to caller. @@ -8381,7 +8012,6 @@ instruct compareAndExchangeB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8396,7 +8026,6 @@ instruct compareAndExchangeB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iR effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8411,7 +8040,6 @@ instruct compareAndExchangeB_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8432,7 +8060,6 @@ instruct compareAndExchangeB4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); format %{ "CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8453,7 +8080,6 @@ instruct compareAndExchangeS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8468,7 +8094,6 @@ instruct compareAndExchangeS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iR effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8483,7 +8108,6 @@ instruct compareAndExchangeS_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8504,7 +8128,6 @@ instruct compareAndExchangeS4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0); format %{ "CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8525,7 +8148,6 @@ instruct compareAndExchangeI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8540,7 +8162,6 @@ instruct compareAndExchangeI_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as int" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8561,7 +8182,6 @@ instruct compareAndExchangeN_regP_regN_regN(iRegNdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as narrow oop" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8576,7 +8196,6 @@ instruct compareAndExchangeN_acq_regP_regN_regN(iRegNdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as narrow oop" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgw(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8597,7 +8216,6 @@ instruct compareAndExchangeL_regP_regL_regL(iRegLdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as long" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8612,7 +8230,6 @@ instruct compareAndExchangeL_acq_regP_regL_regL(iRegLdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as long" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8633,7 +8250,6 @@ instruct compareAndExchangeP_regP_regP_regP(iRegPdst res, iRegPdst mem_ptr, iReg effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as ptr; ptr" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8648,7 +8264,6 @@ instruct compareAndExchangeP_acq_regP_regP_regP(iRegPdst res, iRegPdst mem_ptr, effect(TEMP_DEF res, TEMP cr0); format %{ "CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as ptr; ptr" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'. __ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), @@ -8906,7 +8521,6 @@ instruct addI_reg_reg(iRegIdst dst, iRegIsrc_iRegL2Isrc src1, iRegIsrc_iRegL2Isr format %{ "ADD $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_add); __ add($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -8919,7 +8533,6 @@ instruct addI_reg_reg_2(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "ADD $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_add); __ add($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -8945,7 +8558,6 @@ instruct addI_reg_imm16(iRegIdst dst, iRegIsrc src1, immI16 src2) %{ format %{ "ADDI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ addi($dst$$Register, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -8957,7 +8569,6 @@ instruct addI_reg_immhi16(iRegIdst dst, iRegIsrc src1, immIhi16 src2) %{ format %{ "ADDIS $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); __ addis($dst$$Register, $src1$$Register, ($src2$$constant)>>16); %} ins_pipe(pipe_class_default); @@ -8969,7 +8580,6 @@ instruct addL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "ADD $dst, $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_add); __ add($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -8982,7 +8592,6 @@ instruct addL_reg_reg_2(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "ADD $dst, $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_add); __ add($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9009,7 +8618,6 @@ instruct addI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "ADD $dst, $src1, $src2 \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_add); __ add($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9022,7 +8630,6 @@ instruct addL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ format %{ "ADDI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ addi($dst$$Register, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -9036,7 +8643,6 @@ instruct addL_reg_immhi16(iRegLdst dst, iRegLsrc src1, immL32hi16 src2) %{ format %{ "ADDIS $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); __ addis($dst$$Register, $src1$$Register, ($src2$$constant)>>16); %} ins_pipe(pipe_class_default); @@ -9048,7 +8654,6 @@ instruct addP_reg_reg(iRegPdst dst, iRegP_N2P src1, iRegLsrc src2) %{ format %{ "ADD $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_add); __ add($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9062,7 +8667,6 @@ instruct addP_reg_imm16(iRegPdst dst, iRegP_N2P src1, immL16 src2) %{ format %{ "ADDI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ addi($dst$$Register, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -9076,7 +8680,6 @@ instruct addP_reg_immhi16(iRegPdst dst, iRegP_N2P src1, immL32hi16 src2) %{ format %{ "ADDIS $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addis); __ addis($dst$$Register, $src1$$Register, ($src2$$constant)>>16); %} ins_pipe(pipe_class_default); @@ -9091,7 +8694,6 @@ instruct subI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "SUBF $dst, $src2, $src1" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_subf); __ subf($dst$$Register, $src2$$Register, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -9108,7 +8710,6 @@ instruct subI_imm16_reg(iRegIdst dst, immI16 src1, iRegIsrc src2) %{ size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_subfic); __ subfic($dst$$Register, $src2$$Register, $src1$$constant); %} ins_pipe(pipe_class_default); @@ -9124,7 +8725,6 @@ instruct signmask32I_regI(iRegIdst dst, iRegIsrc src) %{ format %{ "SRAWI $dst, $src, #31" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_srawi); __ srawi($dst$$Register, $src$$Register, 0x1f); %} ins_pipe(pipe_class_default); @@ -9148,7 +8748,6 @@ instruct negI_regI(iRegIdst dst, immI_0 zero, iRegIsrc src2) %{ format %{ "NEG $dst, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_neg); __ neg($dst$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9160,7 +8759,6 @@ instruct subL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "SUBF $dst, $src2, $src1 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_subf); __ subf($dst$$Register, $src2$$Register, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -9173,7 +8771,6 @@ instruct subI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "SUBF $dst, $src2, $src1 \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_subf); __ subf($dst$$Register, $src2$$Register, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -9189,7 +8786,6 @@ instruct signmask64I_regL(iRegIdst dst, iRegLsrc src) %{ format %{ "SRADI $dst, $src, #63" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sradi); __ sradi($dst$$Register, $src$$Register, 0x3f); %} ins_pipe(pipe_class_default); @@ -9205,7 +8801,6 @@ instruct signmask64L_regL(iRegLdst dst, iRegLsrc src) %{ format %{ "SRADI $dst, $src, #63" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sradi); __ sradi($dst$$Register, $src$$Register, 0x3f); %} ins_pipe(pipe_class_default); @@ -9230,7 +8825,6 @@ instruct negL_reg_reg(iRegLdst dst, immL_0 zero, iRegLsrc src2) %{ format %{ "NEG $dst, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_neg); __ neg($dst$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9243,7 +8837,6 @@ instruct negI_con0_regL(iRegIdst dst, immL_0 zero, iRegLsrc src2) %{ format %{ "NEG $dst, $src2 \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_neg); __ neg($dst$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9260,7 +8853,6 @@ instruct mulI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "MULLW $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mullw); __ mullw($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9274,7 +8866,6 @@ instruct mulI_reg_imm16(iRegIdst dst, iRegIsrc src1, immI16 src2) %{ format %{ "MULLI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mulli); __ mulli($dst$$Register, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -9287,7 +8878,6 @@ instruct mulL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "MULLD $dst $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mulld); __ mulld($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9301,7 +8891,6 @@ instruct mulHighL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "MULHD $dst $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mulhd); __ mulhd($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9315,7 +8904,6 @@ instruct mulL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ format %{ "MULLI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mulli); __ mulli($dst$$Register, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -9329,7 +8917,6 @@ instruct divI_reg_immIvalueMinus1(iRegIdst dst, iRegIsrc src1, immI_minus1 src2) format %{ "NEG $dst, $src1 \t// /-1" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_neg); __ neg($dst$$Register, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -9346,7 +8933,6 @@ instruct divI_reg_regnotMinus1(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "DIVW $dst, $src1, $src2 \t// /not-1" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_divw); __ divw($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9360,13 +8946,11 @@ instruct cmovI_bne_negI_reg(iRegIdst dst, flagsRegSrc crx, iRegIsrc src1) %{ format %{ "CMOVE $dst, neg($src1), $crx" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT (InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8)); + size(8); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmove); Label done; __ bne($crx$$CondRegister, done); __ neg($dst$$Register, $src1$$Register); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} ins_pipe(pipe_class_default); @@ -9394,7 +8978,6 @@ instruct divL_reg_immLvalueMinus1(iRegLdst dst, iRegLsrc src1, immL_minus1 src2) format %{ "NEG $dst, $src1 \t// /-1, long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_neg); __ neg($dst$$Register, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -9409,7 +8992,6 @@ instruct divL_reg_regnotMinus1(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "DIVD $dst, $src1, $src2 \t// /not-1, long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_divd); __ divd($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9423,13 +9005,11 @@ instruct cmovL_bne_negL_reg(iRegLdst dst, flagsRegSrc crx, iRegLsrc src1) %{ format %{ "CMOVE $dst, neg($src1), $crx" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT (InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8)); + size(8); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmove); Label done; __ bne($crx$$CondRegister, done); __ neg($dst$$Register, $src1$$Register); - // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} ins_pipe(pipe_class_default); @@ -9499,7 +9079,6 @@ instruct maskI_reg_imm(iRegIdst dst, iRegIsrc src, uimmI6 mask) %{ format %{ "MASK $dst, $src, $mask \t// clear $mask upper bits" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src$$Register, $mask$$constant); %} ins_pipe(pipe_class_default); @@ -9513,7 +9092,6 @@ instruct lShiftI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "SLW $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_slw); __ slw($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9537,7 +9115,6 @@ instruct lShiftI_reg_imm(iRegIdst dst, iRegIsrc src1, immI src2) %{ format %{ "SLWI $dst, $src1, ($src2 & 0x1f)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); __ slwi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x1f); %} ins_pipe(pipe_class_default); @@ -9551,7 +9128,6 @@ instruct lShiftI_andI_immInegpow2_imm5(iRegIdst dst, iRegIsrc src1, immInegpow2 format %{ "RLWINM $dst, lShiftI(AndI($src1, $src2), $src3)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); // FIXME: assert that rlwinm is equal to addi long src2 = $src2$$constant; long src3 = $src3$$constant; long maskbits = src3 + log2_long((jlong) (julong) (juint) -src2); @@ -9572,7 +9148,6 @@ instruct lShiftI_andI_immInegpow2_rShiftI_imm5(iRegIdst dst, iRegIsrc src1, immI format %{ "RLWINM $dst, lShiftI(AndI(RShiftI($src1, $src3), $src2), $src3)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); // FIXME: assert that rlwinm is equal to addi long src2 = $src2$$constant; long src3 = $src3$$constant; long maskbits = src3 + log2_long((jlong) (julong) (juint) -src2); @@ -9593,7 +9168,6 @@ instruct lShiftL_regL_regI(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ format %{ "SLD $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sld); __ sld($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9617,7 +9191,6 @@ instruct lshiftL_regL_immI(iRegLdst dst, iRegLsrc src1, immI src2) %{ format %{ "SLDI $dst, $src1, ($src2 & 0x3f)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ sldi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x3f); %} ins_pipe(pipe_class_default); @@ -9631,7 +9204,6 @@ instruct lShiftL_regI_immGE32(iRegLdst dst, iRegIsrc src1, uimmI6_ge32 src2) %{ size(4); format %{ "SLDI $dst, i2l($src1), $src2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ sldi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x3f); %} ins_pipe(pipe_class_default); @@ -9646,7 +9218,6 @@ instruct scaledPositiveI2L_lShiftL_convI2L_reg_imm6(iRegLdst dst, iRegIsrc src1, format %{ "SLDI $dst, i2l(positive_int($src1)), $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldic); __ clrlsldi($dst$$Register, $src1$$Register, 0x20, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -9660,7 +9231,6 @@ instruct arShiftI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "SRAW $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sraw); __ sraw($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9685,7 +9255,6 @@ instruct arShiftI_reg_imm(iRegIdst dst, iRegIsrc src1, immI src2) %{ format %{ "SRAWI $dst, $src1, ($src2 & 0x1f)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_srawi); __ srawi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x1f); %} ins_pipe(pipe_class_default); @@ -9699,7 +9268,6 @@ instruct arShiftL_regL_regI(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ format %{ "SRAD $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_srad); __ srad($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9725,7 +9293,6 @@ instruct arShiftL_regL_immI(iRegLdst dst, iRegLsrc src1, immI src2) %{ format %{ "SRADI $dst, $src1, ($src2 & 0x3f)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sradi); __ sradi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x3f); %} ins_pipe(pipe_class_default); @@ -9738,7 +9305,6 @@ instruct convL2I_arShiftL_regL_immI(iRegIdst dst, iRegLsrc src1, immI src2) %{ format %{ "SRADI $dst, $src1, ($src2 & 0x3f) \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_sradi); __ sradi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x3f); %} ins_pipe(pipe_class_default); @@ -9752,7 +9318,6 @@ instruct urShiftI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "SRW $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_srw); __ srw($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9778,7 +9343,6 @@ instruct urShiftI_reg_imm(iRegIdst dst, iRegIsrc src1, immI src2) %{ format %{ "SRWI $dst, $src1, ($src2 & 0x1f)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); __ srwi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x1f); %} ins_pipe(pipe_class_default); @@ -9792,7 +9356,6 @@ instruct urShiftL_regL_regI(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ format %{ "SRD $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_srd); __ srd($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -9818,7 +9381,6 @@ instruct urShiftL_regL_immI(iRegLdst dst, iRegLsrc src1, immI src2) %{ format %{ "SRDI $dst, $src1, ($src2 & 0x3f)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ srdi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x3f); %} ins_pipe(pipe_class_default); @@ -9831,7 +9393,6 @@ instruct convL2I_urShiftL_regL_immI(iRegIdst dst, iRegLsrc src1, immI src2) %{ format %{ "SRDI $dst, $src1, ($src2 & 0x3f) \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ srdi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x3f); %} ins_pipe(pipe_class_default); @@ -9844,7 +9405,6 @@ instruct shrP_convP2X_reg_imm6(iRegLdst dst, iRegP_N2P src1, uimmI6 src2) %{ format %{ "SRDI $dst, $src1, $src2 \t// Cast ptr $src1 to long and shift" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ srdi($dst$$Register, $src1$$Register, ($src2$$constant) & 0x3f); %} ins_pipe(pipe_class_default); @@ -9857,7 +9417,6 @@ instruct andI_urShiftI_regI_immI_immIpow2minus1(iRegIdst dst, iRegIsrc src1, imm format %{ "EXTRDI $dst, $src1, shift=$src2, mask=$src3 \t// int bitfield extract" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); int rshift = ($src2$$constant) & 0x1f; int length = log2_long(((jlong) $src3$$constant) + 1); if (rshift + length > 32) { @@ -9876,7 +9435,6 @@ instruct andL_urShiftL_regL_immI_immLpow2minus1(iRegLdst dst, iRegLsrc src1, imm format %{ "EXTRDI $dst, $src1, shift=$src2, mask=$src3 \t// long bitfield extract" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); int rshift = ($src2$$constant) & 0x3f; int length = log2_long(((jlong) $src3$$constant) + 1); if (rshift + length > 64) { @@ -9894,7 +9452,6 @@ instruct sxtI_reg(iRegIdst dst, iRegIsrc src) %{ format %{ "EXTSW $dst, $src \t// int->int" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_extsw); __ extsw($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -9910,7 +9467,6 @@ instruct rotlI_reg_immi8(iRegIdst dst, iRegIsrc src, immI8 lshift, immI8 rshift) format %{ "ROTLWI $dst, $src, $lshift" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); __ rotlwi($dst$$Register, $src$$Register, $lshift$$constant); %} ins_pipe(pipe_class_default); @@ -9924,7 +9480,6 @@ instruct rotrI_reg_immi8(iRegIdst dst, iRegIsrc src, immI8 rshift, immI8 lshift) format %{ "ROTRWI $dst, $rshift" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); __ rotrwi($dst$$Register, $src$$Register, $rshift$$constant); %} ins_pipe(pipe_class_default); @@ -9939,7 +9494,6 @@ instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ format %{ "FADDS $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fadds); __ fadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -9952,7 +9506,6 @@ instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ format %{ "FADD $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fadd); __ fadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -9965,7 +9518,6 @@ instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ format %{ "FSUBS $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fsubs); __ fsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -9977,7 +9529,6 @@ instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ format %{ "FSUB $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fsub); __ fsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -9989,7 +9540,6 @@ instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ format %{ "FMULS $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmuls); __ fmuls($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10001,7 +9551,6 @@ instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ format %{ "FMUL $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmul); __ fmul($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10013,7 +9562,6 @@ instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ format %{ "FDIVS $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fdivs); __ fdivs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10025,7 +9573,6 @@ instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ format %{ "FDIV $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fdiv); __ fdiv($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10037,7 +9584,6 @@ instruct absF_reg(regF dst, regF src) %{ format %{ "FABS $dst, $src \t// float" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fabs); __ fabs($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10049,7 +9595,6 @@ instruct absD_reg(regD dst, regD src) %{ format %{ "FABS $dst, $src \t// double" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fabs); __ fabs($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10060,7 +9605,6 @@ instruct negF_reg(regF dst, regF src) %{ format %{ "FNEG $dst, $src \t// float" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fneg); __ fneg($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10071,7 +9615,6 @@ instruct negD_reg(regD dst, regD src) %{ format %{ "FNEG $dst, $src \t// double" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fneg); __ fneg($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10083,7 +9626,6 @@ instruct negF_absF_reg(regF dst, regF src) %{ format %{ "FNABS $dst, $src \t// float" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fnabs); __ fnabs($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10095,7 +9637,6 @@ instruct negD_absD_reg(regD dst, regD src) %{ format %{ "FNABS $dst, $src \t// double" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fnabs); __ fnabs($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10108,7 +9649,6 @@ instruct sqrtD_reg(regD dst, regD src) %{ format %{ "FSQRT $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fsqrt); __ fsqrt($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10123,7 +9663,6 @@ instruct sqrtF_reg(regF dst, regF src) %{ format %{ "FSQRTS $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fsqrts); __ fsqrts($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10160,7 +9699,6 @@ instruct maddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{ format %{ "FMADDS $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmadds); __ fmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10173,7 +9711,6 @@ instruct maddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{ format %{ "FMADD $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmadd); __ fmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10187,7 +9724,6 @@ instruct mnsubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{ format %{ "FNMSUBS $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fnmsubs); __ fnmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10201,7 +9737,6 @@ instruct mnsubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{ format %{ "FNMSUB $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fnmsub); __ fnmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10215,7 +9750,6 @@ instruct mnaddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{ format %{ "FNMADDS $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fnmadds); __ fnmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10229,7 +9763,6 @@ instruct mnaddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{ format %{ "FNMADD $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fnmadd); __ fnmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10242,7 +9775,6 @@ instruct msubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{ format %{ "FMSUBS $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmsubs); __ fmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10255,7 +9787,6 @@ instruct msubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{ format %{ "FMSUB $dst, $src1, $src2, $src3" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmsub); __ fmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -10272,7 +9803,6 @@ instruct andI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "AND $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_and); __ andr($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10285,7 +9815,6 @@ instruct andI_reg_immIhi16(iRegIdst dst, iRegIsrc src1, immIhi16 src2, flagsReg format %{ "ANDIS $dst, $src1, $src2.hi" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_andis_); __ andis_($dst$$Register, $src1$$Register, (int)((unsigned short)(($src2$$constant & 0xFFFF0000) >> 16))); %} ins_pipe(pipe_class_default); @@ -10299,7 +9828,6 @@ instruct andI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2, flagsRegCR0 format %{ "ANDI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_andi_); // FIXME: avoid andi_ ? __ andi_($dst$$Register, $src1$$Register, $src2$$constant); %} @@ -10312,7 +9840,6 @@ instruct andI_reg_immInegpow2(iRegIdst dst, iRegIsrc src1, immInegpow2 src2) %{ format %{ "ANDWI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ clrrdi($dst$$Register, $src1$$Register, log2_long((jlong)(julong)(juint)-($src2$$constant))); %} ins_pipe(pipe_class_default); @@ -10323,7 +9850,6 @@ instruct andI_reg_immIpow2minus1(iRegIdst dst, iRegIsrc src1, immIpow2minus1 src format %{ "ANDWI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src1$$Register, 64-log2_long((((jlong) $src2$$constant)+1))); %} ins_pipe(pipe_class_default); @@ -10335,7 +9861,6 @@ instruct andI_reg_immIpowerOf2(iRegIdst dst, iRegIsrc src1, immIpowerOf2 src2) % format %{ "ANDWI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); __ rlwinm($dst$$Register, $src1$$Register, 0, (31-log2_long((jlong) $src2$$constant)) & 0x1f, (31-log2_long((jlong) $src2$$constant)) & 0x1f); %} @@ -10350,7 +9875,6 @@ instruct andL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "AND $dst, $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_and); __ andr($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10364,7 +9888,6 @@ instruct andL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 src2, flagsRegCR0 format %{ "ANDI $dst, $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_andi_); // FIXME: avoid andi_ ? __ andi_($dst$$Register, $src1$$Register, $src2$$constant); %} @@ -10377,7 +9900,6 @@ instruct andL_reg_immLnegpow2(iRegLdst dst, iRegLsrc src1, immLnegpow2 src2) %{ format %{ "ANDDI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ clrrdi($dst$$Register, $src1$$Register, log2_long((jlong)-$src2$$constant)); %} ins_pipe(pipe_class_default); @@ -10388,7 +9910,6 @@ instruct andL_reg_immLpow2minus1(iRegLdst dst, iRegLsrc src1, immLpow2minus1 src format %{ "ANDDI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src1$$Register, 64-log2_long((((jlong) $src2$$constant)+1))); %} ins_pipe(pipe_class_default); @@ -10402,7 +9923,6 @@ instruct convL2I_andL_reg_immLpow2minus1(iRegIdst dst, iRegLsrc src1, immLpow2mi format %{ "ANDDI $dst, $src1, $src2 \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src1$$Register, 64-log2_long((((jlong) $src2$$constant)+1))); %} ins_pipe(pipe_class_default); @@ -10416,7 +9936,6 @@ instruct orI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "OR $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10429,7 +9948,6 @@ instruct orI_reg_reg_2(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "OR $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10455,7 +9973,6 @@ instruct orI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2) %{ format %{ "ORI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ori); __ ori($dst$$Register, $src1$$Register, ($src2$$constant) & 0xFFFF); %} ins_pipe(pipe_class_default); @@ -10469,7 +9986,6 @@ instruct orL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ size(4); format %{ "OR $dst, $src1, $src2 \t// long" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10483,7 +9999,6 @@ instruct orI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "OR $dst, $src1, $src2 \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10497,7 +10012,6 @@ instruct orL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 con) %{ format %{ "ORI $dst, $src1, $con \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_ori); __ ori($dst$$Register, $src1$$Register, ($con$$constant) & 0xFFFF); %} ins_pipe(pipe_class_default); @@ -10511,7 +10025,6 @@ instruct xorI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "XOR $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_xor); __ xorr($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10524,7 +10037,6 @@ instruct xorI_reg_reg_2(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ format %{ "XOR $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_xor); __ xorr($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10550,7 +10062,6 @@ instruct xorI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2) %{ format %{ "XORI $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_xori); __ xori($dst$$Register, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -10564,7 +10075,6 @@ instruct xorL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "XOR $dst, $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_xor); __ xorr($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10578,7 +10088,6 @@ instruct xorI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "XOR $dst, $src1, $src2 \t// long + l2i" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_xor); __ xorr($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10592,7 +10101,6 @@ instruct xorL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 src2) %{ format %{ "XORI $dst, $src1, $src2 \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_xori); __ xori($dst$$Register, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_default); @@ -10605,7 +10113,6 @@ instruct notI_reg(iRegIdst dst, iRegIsrc src1, immI_minus1 src2) %{ format %{ "NOT $dst, $src1 ($src2)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_nor); __ nor($dst$$Register, $src1$$Register, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -10618,7 +10125,6 @@ instruct notL_reg(iRegLdst dst, iRegLsrc src1, immL_minus1 src2) %{ format %{ "NOT $dst, $src1 ($src2) \t// long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_nor); __ nor($dst$$Register, $src1$$Register, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -10644,7 +10150,6 @@ instruct andcL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ format %{ "ANDC $dst, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_andc); __ andc($dst$$Register, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_default); @@ -10771,7 +10276,6 @@ instruct moveI2F_stack_reg(regF dst, stackSlotI src) %{ format %{ "LFS $dst, $src \t// MoveI2F" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_lfs); int Idisp = $src$$disp + frame_slots_bias($src$$base, ra_); __ lfs($dst$$FloatRegister, Idisp, $src$$base$$Register); %} @@ -10859,7 +10363,6 @@ instruct moveReg(iRegLdst dst, iRegIsrc src) %{ format %{ "MR $dst, $src \t// replicate " %} // variable size, 0 or 4. ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ mr_if_needed($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -10874,7 +10377,6 @@ instruct castX2P(iRegPdst dst, iRegLsrc src) %{ format %{ "MR $dst, $src \t// Long->Ptr" %} // variable size, 0 or 4. ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ mr_if_needed($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -10887,7 +10389,6 @@ instruct castP2X(iRegLdst dst, iRegP_N2P src) %{ format %{ "MR $dst, $src \t// Ptr->Long" %} // variable size, 0 or 4. ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ mr_if_needed($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -11002,7 +10503,6 @@ instruct convI2Bool_andI_reg_immIpowerOf2(iRegIdst dst, iRegIsrc src, immIpowerO format %{ "RLWINM $dst, $src, $mask \t// convI2B(AndI($src, $mask))" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwinm); __ rlwinm($dst$$Register, $src$$Register, (32-log2_long((jlong)$mask$$constant)) & 0x1f, 31, 31); %} ins_pipe(pipe_class_default); @@ -11104,7 +10604,6 @@ instruct cmpLTMask_reg_immI0(iRegIdst dst, iRegIsrc src1, immI_0 src2) %{ format %{ "SRAWI $dst, $src1, $src2 \t// CmpLTMask" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_srawi); __ srawi($dst$$Register, $src1$$Register, 0x1f); %} ins_pipe(pipe_class_default); @@ -11122,7 +10621,6 @@ instruct convB2I_reg(iRegIdst dst, iRegIsrc src, immI_24 amount) %{ format %{ "EXTSB $dst, $src \t// byte->int" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_extsb); __ extsb($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -11144,7 +10642,6 @@ instruct convS2I_reg(iRegIdst dst, iRegIsrc src, immI_16 amount) %{ format %{ "EXTSH $dst, $src \t// short->int" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_extsh); __ extsh($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -11157,7 +10654,6 @@ instruct sxtI_L2L_reg(iRegLdst dst, iRegLsrc src) %{ format %{ "EXTSW $dst, $src \t// long->long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_extsw); __ extsw($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -11168,7 +10664,6 @@ instruct convL2I_reg(iRegIdst dst, iRegLsrc src) %{ format %{ "MR $dst, $src \t// long->int" %} // variable size, 0 or 4 ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_or); __ mr_if_needed($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -11182,7 +10677,6 @@ instruct convD2IRaw_regD(regD dst, regD src) %{ format %{ "FCTIWZ $dst, $src \t// convD2I, $src != NaN" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fctiwz);; __ fctiwz($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11197,7 +10691,7 @@ instruct cmovI_bso_stackSlotL(iRegIdst dst, flagsRegSrc crx, stackSlotL src) %{ format %{ "cmovI $crx, $dst, $src" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT(InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) ); ins_pipe(pipe_class_default); %} @@ -11211,7 +10705,7 @@ instruct cmovI_bso_reg(iRegIdst dst, flagsRegSrc crx, regD src) %{ format %{ "cmovI $crx, $dst, $src" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT(InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_bso_reg(dst, crx, src) ); ins_pipe(pipe_class_default); %} @@ -11364,7 +10858,6 @@ instruct convF2IRaw_regF(regF dst, regF src) %{ format %{ "FCTIWZ $dst, $src \t// convF2I, $src != NaN" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fctiwz); __ fctiwz($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11409,7 +10902,6 @@ instruct convI2L_reg(iRegLdst dst, iRegIsrc src) %{ format %{ "EXTSW $dst, $src \t// int->long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_extsw); __ extsw($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -11423,7 +10915,6 @@ instruct zeroExtendL_regI(iRegLdst dst, iRegIsrc src, immL_32bits mask) %{ format %{ "CLRLDI $dst, $src, #32 \t// zero-extend int to long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src$$Register, 32); %} ins_pipe(pipe_class_default); @@ -11437,7 +10928,6 @@ instruct zeroExtendL_regL(iRegLdst dst, iRegLsrc src, immL_32bits mask) %{ format %{ "CLRLDI $dst, $src, #32 \t// zero-extend int to long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); __ clrldi($dst$$Register, $src$$Register, 32); %} ins_pipe(pipe_class_default); @@ -11451,7 +10941,6 @@ instruct convF2LRaw_regF(regF dst, regF src) %{ format %{ "FCTIDZ $dst, $src \t// convF2L, $src != NaN" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fctiwz); __ fctidz($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11466,7 +10955,7 @@ instruct cmovL_bso_stackSlotL(iRegLdst dst, flagsRegSrc crx, stackSlotL src) %{ format %{ "cmovL $crx, $dst, $src" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) ); ins_pipe(pipe_class_default); %} @@ -11480,7 +10969,7 @@ instruct cmovL_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{ format %{ "cmovL $crx, $dst, $src" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8)); + size(8); ins_encode( enc_cmove_bso_reg(dst, crx, src) ); ins_pipe(pipe_class_default); %} @@ -11627,7 +11116,6 @@ instruct convD2LRaw_regD(regD dst, regD src) %{ format %{ "FCTIDZ $dst, $src \t// convD2L $src != NaN" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fctiwz); __ fctidz($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11676,7 +11164,6 @@ instruct convL2DRaw_regD(regD dst, regD src) %{ format %{ "FCFID $dst, $src \t// convL2D" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fcfid); __ fcfid($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11688,7 +11175,6 @@ instruct convD2F_reg(regF dst, regD src) %{ format %{ "FRSP $dst, $src \t// convD2F" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_frsp); __ frsp($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11721,7 +11207,6 @@ instruct convL2FRaw_regF(regF dst, regD src) %{ format %{ "FCFIDS $dst, $src \t// convL2F" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fcfid); __ fcfids($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11850,7 +11335,6 @@ instruct convF2D_reg(regD dst, regF src) %{ format %{ "FMR $dst, $src \t// float->double" %} // variable size, 0 or 4 ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmr); __ fmr_if_needed($dst$$FloatRegister, $src$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -11865,7 +11349,6 @@ instruct cmpI_reg_reg(flagsReg crx, iRegIsrc src1, iRegIsrc src2) %{ size(4); format %{ "CMPW $crx, $src1, $src2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmp); __ cmpw($crx$$CondRegister, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_compare); @@ -11876,7 +11359,6 @@ instruct cmpI_reg_imm16(flagsReg crx, iRegIsrc src1, immI16 src2) %{ format %{ "CMPWI $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpi); __ cmpwi($crx$$CondRegister, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -11889,7 +11371,6 @@ instruct testI_reg_imm(flagsRegCR0 cr0, iRegIsrc src1, uimmI16 src2, immI_0 zero format %{ "ANDI R0, $src1, $src2 \t// BTST int" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_andi_); __ andi_(R0, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -11900,7 +11381,6 @@ instruct cmpL_reg_reg(flagsReg crx, iRegLsrc src1, iRegLsrc src2) %{ format %{ "CMPD $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmp); __ cmpd($crx$$CondRegister, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_compare); @@ -11911,7 +11391,6 @@ instruct cmpL_reg_imm16(flagsReg crx, iRegLsrc src1, immL16 src2) %{ format %{ "CMPDI $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpi); __ cmpdi($crx$$CondRegister, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -11923,7 +11402,6 @@ instruct cmpUL_reg_reg(flagsReg crx, iRegLsrc src1, iRegLsrc src2) %{ format %{ "CMPLD $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpl); __ cmpld($crx$$CondRegister, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_compare); @@ -11934,7 +11412,6 @@ instruct cmpUL_reg_imm16(flagsReg crx, iRegLsrc src1, uimmL16 src2) %{ format %{ "CMPLDI $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpli); __ cmpldi($crx$$CondRegister, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -11946,7 +11423,6 @@ instruct testL_reg_reg(flagsRegCR0 cr0, iRegLsrc src1, iRegLsrc src2, immL_0 zer format %{ "AND R0, $src1, $src2 \t// BTST long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_and_); __ and_(R0, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_compare); @@ -11958,7 +11434,6 @@ instruct testL_reg_imm(flagsRegCR0 cr0, iRegLsrc src1, uimmL16 src2, immL_0 zero format %{ "ANDI R0, $src1, $src2 \t// BTST long" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_andi_); __ andi_(R0, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -11973,16 +11448,14 @@ instruct cmovI_conIvalueMinus1_conIvalue1(iRegIdst dst, flagsRegSrc crx) %{ format %{ "cmovI $crx, $dst, -1, 0, +1" %} // Worst case is branch + move + branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORTInsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 20 : 16)); + size(16); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmove); Label done; // li(Rdst, 0); // equal -> 0 __ beq($crx$$CondRegister, done); __ li($dst$$Register, 1); // greater -> +1 __ bgt($crx$$CondRegister, done); __ li($dst$$Register, -1); // unordered or less -> -1 - // TODO: PPC port__ endgroup_if_needed(_size == 20); __ bind(done); %} ins_pipe(pipe_class_compare); @@ -12071,7 +11544,6 @@ instruct rangeCheck_iReg_uimm15(cmpOp cmp, iRegIsrc src_length, uimmI15 index, l format %{ "TWI $index $cmp $src_length \t// RangeCheck => trap $labl" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_twi); if ($cmp$$cmpcode == 0x1 /* less_equal */) { __ trap_range_check_le($src_length$$Register, $index$$constant); } else { @@ -12098,7 +11570,6 @@ instruct rangeCheck_iReg_iReg(cmpOp cmp, iRegIsrc src_index, iRegIsrc src_length format %{ "TW $src_index $cmp $src_length \t// RangeCheck => trap $labl" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_tw); if ($cmp$$cmpcode == 0x0 /* greater_equal */) { __ trap_range_check_ge($src_index$$Register, $src_length$$Register); } else { @@ -12125,7 +11596,6 @@ instruct rangeCheck_uimm15_iReg(cmpOp cmp, iRegIsrc src_index, uimmI15 length, l format %{ "TWI $src_index $cmp $length \t// RangeCheck => trap $labl" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_twi); if ($cmp$$cmpcode == 0x0 /* greater_equal */) { __ trap_range_check_ge($src_index$$Register, $length$$constant); } else { @@ -12143,7 +11613,6 @@ instruct compU_reg_reg(flagsReg crx, iRegIsrc src1, iRegIsrc src2) %{ format %{ "CMPLW $crx, $src1, $src2 \t// unsigned" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpl); __ cmplw($crx$$CondRegister, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_compare); @@ -12154,7 +11623,6 @@ instruct compU_reg_uimm16(flagsReg crx, iRegIsrc src1, uimmI16 src2) %{ size(4); format %{ "CMPLWI $crx, $src1, $src2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpli); __ cmplwi($crx$$CondRegister, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -12176,7 +11644,6 @@ instruct zeroCheckN_iReg_imm0(cmpOp cmp, iRegNsrc value, immN_0 zero, label labl format %{ "TDI $value $cmp $zero \t// ZeroCheckN => trap $labl" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_tdi); if ($cmp$$cmpcode == 0xA) { __ trap_null_check($value$$Register); } else { @@ -12197,7 +11664,6 @@ instruct cmpN_reg_reg(flagsReg crx, iRegNsrc src1, iRegNsrc src2) %{ ins_cost(2); format %{ "CMPLW $crx, $src1, $src2 \t// compressed ptr" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpl); __ cmplw($crx$$CondRegister, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_compare); @@ -12211,7 +11677,6 @@ instruct cmpN_reg_imm0(flagsReg crx, iRegNsrc src1, immN_0 src2) %{ format %{ "CMPLWI $crx, $src1, $src2 \t// compressed ptr" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpli); __ cmplwi($crx$$CondRegister, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -12233,7 +11698,6 @@ instruct zeroCheckP_reg_imm0(cmpOp cmp, iRegP_N2P value, immP_0 zero, label labl format %{ "TDI $value $cmp $zero \t// ZeroCheckP => trap $labl" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_tdi); if ($cmp$$cmpcode == 0xA) { __ trap_null_check($value$$Register); } else { @@ -12252,7 +11716,6 @@ instruct cmpP_reg_reg(flagsReg crx, iRegP_N2P src1, iRegP_N2P src2) %{ format %{ "CMPLD $crx, $src1, $src2 \t// ptr" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpl); __ cmpld($crx$$CondRegister, $src1$$Register, $src2$$Register); %} ins_pipe(pipe_class_compare); @@ -12263,7 +11726,6 @@ instruct cmpP_reg_null(flagsReg crx, iRegP_N2P src1, immP_0or1 src2) %{ format %{ "CMPLDI $crx, $src1, $src2 \t// ptr" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpl); __ cmpldi($crx$$CondRegister, $src1$$Register, (int)((short)($src2$$constant & 0xFFFF))); %} ins_pipe(pipe_class_compare); @@ -12280,7 +11742,6 @@ instruct cmpP_reg_imm16(flagsReg crx, iRegPsrc src1, immL16 src2) %{ format %{ "CMPDI $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmpi); __ cmpdi($crx$$CondRegister, $src1$$Register, $src2$$constant); %} ins_pipe(pipe_class_compare); @@ -12297,7 +11758,6 @@ instruct cmpFUnordered_reg_reg(flagsReg crx, regF src1, regF src2) %{ format %{ "cmpFUrd $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fcmpu); __ fcmpu($crx$$CondRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -12312,14 +11772,12 @@ instruct cmov_bns_less(flagsReg crx) %{ format %{ "cmov $crx" %} // Worst case is branch + move + stop, no stop without scheduler. - size((false /* TODO: PPC PORT(InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 16 : 12)); + size(12); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cmovecr); Label done; __ bns($crx$$CondRegister, done); // not unordered -> keep crx __ li(R0, 0); __ cmpwi($crx$$CondRegister, R0, 1); // unordered -> set crx to 'less' - // TODO PPC port __ endgroup_if_needed(_size == 16); __ bind(done); %} ins_pipe(pipe_class_default); @@ -12412,7 +11870,6 @@ instruct cmpDUnordered_reg_reg(flagsReg crx, regD src1, regD src2) %{ format %{ "cmpFUrd $crx, $src1, $src2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fcmpu); __ fcmpu($crx$$CondRegister, $src1$$FloatRegister, $src2$$FloatRegister); %} ins_pipe(pipe_class_default); @@ -12617,7 +12074,6 @@ instruct branch(label labl) %{ format %{ "B $labl" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_b); Label d; // dummy __ bind(d); Label* p = $labl$$label; @@ -12657,7 +12113,6 @@ instruct branchConFar(cmpOp cmp, flagsRegSrc crx, label lbl) %{ // Same match rule as `branchCon'. match(If cmp crx); effect(USE crx, USE lbl); - predicate(!false /* TODO: PPC port HB_Schedule*/); // Higher cost than `branchCon'. ins_cost(5*BRANCH_COST); @@ -12670,26 +12125,6 @@ instruct branchConFar(cmpOp cmp, flagsRegSrc crx, label lbl) %{ ins_pipe(pipe_class_default); %} -// Conditional Branch used with Power6 scheduler (can be far or short). -instruct branchConSched(cmpOp cmp, flagsRegSrc crx, label lbl) %{ - // Same match rule as `branchCon'. - match(If cmp crx); - effect(USE crx, USE lbl); - predicate(false /* TODO: PPC port HB_Schedule*/); - // Higher cost than `branchCon'. - ins_cost(5*BRANCH_COST); - - // Actually size doesn't depend on alignment but on shortening. - ins_variable_size_depending_on_alignment(true); - // long variant. - ins_short_branch(0); - - format %{ "B_FAR$cmp $crx, $lbl" %} - size(8); // worst case - ins_encode( enc_bc_short_far(crx, cmp, lbl) ); - ins_pipe(pipe_class_default); -%} - instruct branchLoopEnd(cmpOp cmp, flagsRegSrc crx, label labl) %{ match(CountedLoopEnd cmp crx); effect(USE labl); @@ -12707,7 +12142,6 @@ instruct branchLoopEnd(cmpOp cmp, flagsRegSrc crx, label labl) %{ instruct branchLoopEndFar(cmpOp cmp, flagsRegSrc crx, label labl) %{ match(CountedLoopEnd cmp crx); effect(USE labl); - predicate(!false /* TODO: PPC port HB_Schedule */); ins_cost(BRANCH_COST); // Long variant. @@ -12719,25 +12153,6 @@ instruct branchLoopEndFar(cmpOp cmp, flagsRegSrc crx, label labl) %{ ins_pipe(pipe_class_default); %} -// Conditional Branch used with Power6 scheduler (can be far or short). -instruct branchLoopEndSched(cmpOp cmp, flagsRegSrc crx, label labl) %{ - match(CountedLoopEnd cmp crx); - effect(USE labl); - predicate(false /* TODO: PPC port HB_Schedule */); - // Higher cost than `branchCon'. - ins_cost(5*BRANCH_COST); - - // Actually size doesn't depend on alignment but on shortening. - ins_variable_size_depending_on_alignment(true); - // Long variant. - ins_short_branch(0); - - format %{ "B_FAR$cmp $crx, $labl \t// counted loop end" %} - size(8); // worst case - ins_encode( enc_bc_short_far(crx, cmp, labl) ); - ins_pipe(pipe_class_default); -%} - // ============================================================================ // Java runtime operations, intrinsics and other complex operations. @@ -12757,7 +12172,6 @@ instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P supe format %{ "PartialSubtypeCheck $result = ($subklass instanceOf $superklass) tmp: $tmp_klass, $tmp_arrayptr" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ check_klass_subtype_slow_path($subklass$$Register, $superklass$$Register, $tmp_arrayptr$$Register, $tmp_klass$$Register, NULL, $result$$Register); %} @@ -12773,7 +12187,6 @@ instruct cmpFastLock(flagsReg crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iR format %{ "FASTLOCK $oop, $box, $tmp1, $tmp2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ compiler_fast_lock_object($crx$$CondRegister, $oop$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register, /*tmp3*/ R0, UseBiasedLocking && !UseOptoBiasInlining); @@ -12792,7 +12205,6 @@ instruct cmpFastLock_tm(flagsReg crx, iRegPdst oop, rarg2RegP box, iRegPdst tmp1 format %{ "FASTLOCK $oop, $box, $tmp1, $tmp2, $tmp3 (TM)" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ compiler_fast_lock_object($crx$$CondRegister, $oop$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, /*Biased Locking*/ false, @@ -12813,7 +12225,6 @@ instruct cmpFastUnlock(flagsReg crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, format %{ "FASTUNLOCK $oop, $box, $tmp1, $tmp2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ compiler_fast_unlock_object($crx$$CondRegister, $oop$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, UseBiasedLocking && !UseOptoBiasInlining, @@ -12832,7 +12243,6 @@ instruct cmpFastUnlock_tm(flagsReg crx, iRegPdst oop, iRegPdst box, iRegPdst tmp format %{ "FASTUNLOCK $oop, $box, $tmp1, $tmp2 (TM)" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ compiler_fast_unlock_object($crx$$CondRegister, $oop$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, /*Biased Locking*/ false, /*TM*/ true); @@ -12850,7 +12260,6 @@ instruct align_addr(iRegPdst dst, iRegPsrc src, immLnegpow2 mask) %{ format %{ "ANDDI $dst, $src, $mask \t// next aligned address" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); __ clrrdi($dst$$Register, $src$$Register, log2_long((jlong)-$mask$$constant)); %} ins_pipe(pipe_class_default); @@ -12863,7 +12272,6 @@ instruct array_size(iRegLdst dst, iRegPsrc end, iRegPsrc start) %{ format %{ "SUB $dst, $end, $start \t// array size in bytes" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_subf); __ subf($dst$$Register, $start$$Register, $end$$Register); %} ins_pipe(pipe_class_default); @@ -12877,7 +12285,6 @@ instruct inlineCallClearArrayShort(immLmax30 cnt, rarg2RegP base, Universe dummy format %{ "ClearArray $cnt, $base" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ clear_memory_constlen($base$$Register, $cnt$$constant, R0); // kills base, R0 %} ins_pipe(pipe_class_default); @@ -12891,7 +12298,6 @@ instruct inlineCallClearArrayLarge(immL cnt, rarg2RegP base, Universe dummy, iRe format %{ "ClearArray $cnt, $base \t// KILL $tmp" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ clear_memory_doubleword($base$$Register, $tmp$$Register, R0, $cnt$$constant); // kills base, R0 %} ins_pipe(pipe_class_default); @@ -12905,7 +12311,6 @@ instruct inlineCallClearArray(rarg1RegL cnt, rarg2RegP base, Universe dummy, reg format %{ "ClearArray $cnt, $base" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ clear_memory_doubleword($base$$Register, $cnt$$Register, R0); // kills cnt, base, R0 %} ins_pipe(pipe_class_default); @@ -12919,7 +12324,6 @@ instruct string_compareL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4Re ins_cost(300); format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $tmp$$Register, @@ -12936,7 +12340,6 @@ instruct string_compareU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4Re ins_cost(300); format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $tmp$$Register, @@ -12953,7 +12356,6 @@ instruct string_compareLU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4R ins_cost(300); format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $tmp$$Register, @@ -12970,7 +12372,6 @@ instruct string_compareUL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4R ins_cost(300); format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_compare($str2$$Register, $str1$$Register, $cnt2$$Register, $cnt1$$Register, $tmp$$Register, @@ -12987,7 +12388,6 @@ instruct string_equalsL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst ins_cost(300); format %{ "String Equals byte[] $str1,$str2,$cnt -> $result \t// KILL $tmp" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ array_equals(false, $str1$$Register, $str2$$Register, $cnt$$Register, $tmp$$Register, $result$$Register, true /* byte */); @@ -13003,7 +12403,6 @@ instruct string_equalsU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst ins_cost(300); format %{ "String Equals char[] $str1,$str2,$cnt -> $result \t// KILL $tmp" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ array_equals(false, $str1$$Register, $str2$$Register, $cnt$$Register, $tmp$$Register, $result$$Register, false /* byte */); @@ -13019,7 +12418,6 @@ instruct array_equalsB(rarg1RegP ary1, rarg2RegP ary2, iRegIdst result, ins_cost(300); format %{ "Array Equals $ary1,$ary2 -> $result \t// KILL $tmp1,$tmp2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ array_equals(true, $ary1$$Register, $ary2$$Register, $tmp1$$Register, $tmp2$$Register, $result$$Register, true /* byte */); @@ -13035,7 +12433,6 @@ instruct array_equalsC(rarg1RegP ary1, rarg2RegP ary2, iRegIdst result, ins_cost(300); format %{ "Array Equals $ary1,$ary2 -> $result \t// KILL $tmp1,$tmp2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ array_equals(true, $ary1$$Register, $ary2$$Register, $tmp1$$Register, $tmp2$$Register, $result$$Register, false /* byte */); @@ -13057,7 +12454,6 @@ instruct indexOf_imm1_char_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); immPOper *needleOper = (immPOper *)$needleImm; const TypeOopPtr *t = needleOper->type()->isa_oopptr(); ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char * @@ -13091,7 +12487,6 @@ instruct indexOf_imm1_char_L(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); immPOper *needleOper = (immPOper *)$needleImm; const TypeOopPtr *t = needleOper->type()->isa_oopptr(); ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char * @@ -13118,7 +12513,6 @@ instruct indexOf_imm1_char_UL(iRegIdst result, iRegPsrc haystack, iRegIsrc haycn "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); immPOper *needleOper = (immPOper *)$needleImm; const TypeOopPtr *t = needleOper->type()->isa_oopptr(); ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char * @@ -13146,7 +12540,6 @@ instruct indexOf_imm1_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]" " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Node *ndl = in(operand_index($needle)); // The node that defines needle. ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); guarantee(needle_values, "sanity"); @@ -13181,7 +12574,6 @@ instruct indexOf_imm1_L(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]" " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Node *ndl = in(operand_index($needle)); // The node that defines needle. ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); guarantee(needle_values, "sanity"); @@ -13209,7 +12601,6 @@ instruct indexOf_imm1_UL(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]" " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Node *ndl = in(operand_index($needle)); // The node that defines needle. ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); guarantee(needle_values, "sanity"); @@ -13232,7 +12623,6 @@ instruct indexOfChar_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, format %{ "String IndexOfChar $haystack[0..$haycnt], $ch" " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_indexof_char($result$$Register, $haystack$$Register, $haycnt$$Register, $ch$$Register, 0 /* this is not used if the character is already in a register */, @@ -13257,7 +12647,6 @@ instruct indexOf_imm_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]" " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Node *ndl = in(operand_index($needle)); // The node that defines needle. ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); @@ -13285,7 +12674,6 @@ instruct indexOf_imm_L(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]" " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Node *ndl = in(operand_index($needle)); // The node that defines needle. ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); @@ -13313,7 +12701,6 @@ instruct indexOf_imm_UL(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]" " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Node *ndl = in(operand_index($needle)); // The node that defines needle. ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); @@ -13338,7 +12725,6 @@ instruct indexOf_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRe format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]" " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_indexof($result$$Register, $haystack$$Register, $haycnt$$Register, $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant. @@ -13360,7 +12746,6 @@ instruct indexOf_L(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRe format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]" " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_indexof($result$$Register, $haystack$$Register, $haycnt$$Register, $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant. @@ -13382,7 +12767,6 @@ instruct indexOf_UL(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iR format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]" " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ string_indexof($result$$Register, $haystack$$Register, $haycnt$$Register, $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant. @@ -13400,7 +12784,6 @@ instruct string_compress(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst re ins_cost(300); format %{ "String Compress $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Label Lskip, Ldone; __ li($result$$Register, 0); __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, @@ -13423,7 +12806,6 @@ instruct string_inflate(Universe dummy, rarg1RegP src, rarg2RegP dst, iRegIsrc l ins_cost(300); format %{ "String Inflate $src,$dst,$len \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Label Ldone; __ string_inflate_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register); @@ -13444,7 +12826,6 @@ instruct has_negatives(rarg1RegP ary1, iRegIsrc len, iRegIdst result, iRegLdst t ins_cost(300); format %{ "has negatives byte[] $ary1,$len -> $result \t// KILL $tmp1, $tmp2" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ has_negatives($ary1$$Register, $len$$Register, $result$$Register, $tmp1$$Register, $tmp2$$Register); %} @@ -13460,7 +12841,6 @@ instruct encode_iso_array(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst r ins_cost(300); format %{ "Encode array $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); Label Lslow, Lfailure1, Lfailure2, Ldone; __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, Lfailure1); @@ -13517,7 +12897,6 @@ instruct minI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegC ins_cost(DEFAULT_COST*2); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ cmpw(CCR0, $src1$$Register, $src2$$Register); __ isel($dst$$Register, CCR0, Assembler::less, /*invert*/false, $src1$$Register, $src2$$Register); %} @@ -13551,7 +12930,6 @@ instruct maxI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegC ins_cost(DEFAULT_COST*2); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ cmpw(CCR0, $src1$$Register, $src2$$Register); __ isel($dst$$Register, CCR0, Assembler::greater, /*invert*/false, $src1$$Register, $src2$$Register); %} @@ -13569,7 +12947,6 @@ instruct popCountI(iRegIdst dst, iRegIsrc src) %{ format %{ "POPCNTW $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_popcntb); __ popcntw($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -13584,7 +12961,6 @@ instruct popCountL(iRegIdst dst, iRegLsrc src) %{ format %{ "POPCNTD $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_popcntb); __ popcntd($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -13598,7 +12974,6 @@ instruct countLeadingZerosI(iRegIdst dst, iRegIsrc src) %{ format %{ "CNTLZW $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cntlzw); __ cntlzw($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -13612,7 +12987,6 @@ instruct countLeadingZerosL(iRegIdst dst, iRegLsrc src) %{ format %{ "CNTLZD $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cntlzd); __ cntlzd($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -13626,7 +13000,6 @@ instruct countLeadingZerosP(iRegIdst dst, iRegPsrc src) %{ format %{ "CNTLZD $dst, $src" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_cntlzd); __ cntlzd($dst$$Register, $src$$Register); %} ins_pipe(pipe_class_default); @@ -13703,7 +13076,6 @@ instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ format %{ "INSRWI $dst, $src, $pos, $shift" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwimi); __ insrwi($dst$$Register, $src$$Register, $shift$$constant, $pos$$constant); %} ins_pipe(pipe_class_default); @@ -13717,7 +13089,6 @@ instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ format %{ "INSRWI $dst, $src, $pos, $shift" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rlwimi); __ insrwi($dst$$Register, $src$$Register, $shift$$constant, $pos$$constant); %} ins_pipe(pipe_class_default); @@ -14112,7 +13483,6 @@ instruct repl32(iRegLdst dst) %{ format %{ "INSRDI $dst, #0, $dst, #32 \t// replicate" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldimi); __ insrdi($dst$$Register, $dst$$Register, 32, 0); %} ins_pipe(pipe_class_default); @@ -14126,7 +13496,6 @@ instruct repl48(iRegLdst dst) %{ format %{ "INSRDI $dst, #0, $dst, #48 \t// replicate" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldimi); __ insrdi($dst$$Register, $dst$$Register, 48, 0); %} ins_pipe(pipe_class_default); @@ -14140,7 +13509,6 @@ instruct repl56(iRegLdst dst) %{ format %{ "INSRDI $dst, #0, $dst, #56 \t// replicate" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_rldimi); __ insrdi($dst$$Register, $dst$$Register, 56, 0); %} ins_pipe(pipe_class_default); @@ -14163,7 +13531,6 @@ instruct repl8B_immI0(iRegLdst dst, immI_0 zero) %{ format %{ "LI $dst, #0 \t// replicate8B" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($zero$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -14175,7 +13542,6 @@ instruct repl8B_immIminus1(iRegLdst dst, immI_minus1 src) %{ format %{ "LI $dst, #-1 \t// replicate8B" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($src$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -14237,7 +13603,6 @@ instruct repl4S_immI0(iRegLdst dst, immI_0 zero) %{ format %{ "LI $dst, #0 \t// replicate4S" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($zero$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -14249,7 +13614,6 @@ instruct repl4S_immIminus1(iRegLdst dst, immI_minus1 src) %{ format %{ "LI $dst, -1 \t// replicate4S" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($src$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -14311,7 +13675,6 @@ instruct repl2I_immI0(iRegLdst dst, immI_0 zero) %{ format %{ "LI $dst, #0 \t// replicate2I" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($zero$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -14323,7 +13686,6 @@ instruct repl2I_immIminus1(iRegLdst dst, immI_minus1 src) %{ format %{ "LI $dst, -1 \t// replicate2I" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, (int)((short)($src$$constant & 0xFFFF))); %} ins_pipe(pipe_class_default); @@ -14401,7 +13763,6 @@ instruct repl2F_immF0(iRegLdst dst, immF_0 zero) %{ format %{ "LI $dst, #0 \t// replicate2F" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); __ li($dst$$Register, 0x0); %} ins_pipe(pipe_class_default); @@ -14849,7 +14210,6 @@ instruct overflowAddL_reg_reg(flagsRegCR0 cr0, iRegLsrc op1, iRegLsrc op2) %{ format %{ "add_ $op1, $op2\t# overflow check long" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ li(R0, 0); __ mtxer(R0); // clear XER.SO __ addo_(R0, $op1$$Register, $op2$$Register); @@ -14862,7 +14222,6 @@ instruct overflowSubL_reg_reg(flagsRegCR0 cr0, iRegLsrc op1, iRegLsrc op2) %{ format %{ "subfo_ R0, $op2, $op1\t# overflow check long" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ li(R0, 0); __ mtxer(R0); // clear XER.SO __ subfo_(R0, $op2$$Register, $op1$$Register); @@ -14875,7 +14234,6 @@ instruct overflowNegL_reg(flagsRegCR0 cr0, immL_0 zero, iRegLsrc op2) %{ format %{ "nego_ R0, $op2\t# overflow check long" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ li(R0, 0); __ mtxer(R0); // clear XER.SO __ nego_(R0, $op2$$Register); @@ -14888,7 +14246,6 @@ instruct overflowMulL_reg_reg(flagsRegCR0 cr0, iRegLsrc op1, iRegLsrc op2) %{ format %{ "mulldo_ R0, $op1, $op2\t# overflow check long" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ li(R0, 0); __ mtxer(R0); // clear XER.SO __ mulldo_(R0, $op1$$Register, $op2$$Register); @@ -15153,7 +14510,6 @@ instruct CallLeafDirect(method meth) %{ format %{ "BCTRL \t// leaf call $meth ==> " %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_bctrl); __ bctrl(); %} ins_pipe(pipe_class_call); @@ -15202,7 +14558,6 @@ instruct TailCalljmpInd(iRegPdstNoScratch jump_target, inline_cache_regP method_ "BCTR \t// tail call" %} size(8); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ mtctr($jump_target$$Register); __ bctr(); %} @@ -15215,7 +14570,6 @@ instruct Ret() %{ format %{ "BLR \t// branch to link register" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_blr); // LR is restored in MachEpilogNode. Just do the RET here. __ blr(); %} @@ -15237,7 +14591,6 @@ instruct tailjmpInd(iRegPdstNoScratch jump_target, rarg1RegP ex_oop) %{ "BCTR \t// TailJump, exception oop: $ex_oop" %} size(12); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ ld(R4_ARG2/* issuing pc */, _abi(lr), R1_SP); __ mtctr($jump_target$$Register); __ bctr(); @@ -15266,7 +14619,6 @@ instruct RethrowException() %{ format %{ "Jmp rethrow_stub" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_compound); cbuf.set_insts_mark(); __ b64_patchable((address)OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type); %} @@ -15281,7 +14633,6 @@ instruct ShouldNotReachHere() %{ format %{ "ShouldNotReachHere" %} ins_encode %{ if (is_reachable()) { - // TODO: PPC port $archOpcode(ppc64Opcode_tdi); __ stop(_halt_reason); } %} @@ -15315,7 +14666,6 @@ instruct endGroup() %{ format %{ "End Bundle (ori r1, r1, 0)" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_endgroup); __ endgroup(); %} ins_pipe(pipe_class_default); @@ -15331,7 +14681,6 @@ instruct fxNop() %{ format %{ "fxNop" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmr); __ nop(); %} ins_pipe(pipe_class_default); @@ -15345,7 +14694,6 @@ instruct fpNop0() %{ format %{ "fpNop0" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmr); __ fpnop0(); %} ins_pipe(pipe_class_default); @@ -15359,7 +14707,6 @@ instruct fpNop1() %{ format %{ "fpNop1" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_fmr); __ fpnop1(); %} ins_pipe(pipe_class_default); @@ -15370,7 +14717,6 @@ instruct brNop0() %{ size(4); format %{ "brNop0" %} ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mcrf); __ brnop0(); %} ins_is_nop(true); @@ -15385,7 +14731,6 @@ instruct brNop1() %{ format %{ "brNop1" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mcrf); __ brnop1(); %} ins_pipe(pipe_class_default); @@ -15399,7 +14744,6 @@ instruct brNop2() %{ format %{ "brNop2" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_mcrf); __ brnop2(); %} ins_pipe(pipe_class_default); diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 9b729b5baa9..a1f2df08454 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -29,6 +29,7 @@ #include "asm/macroAssembler.inline.hpp" #include "compiler/disassembler.hpp" #include "memory/resourceArea.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" @@ -116,13 +117,6 @@ void VM_Version::initialize() { FLAG_SET_ERGO(TrapBasedRangeChecks, false); } - // On Power6 test for section size. - if (PowerArchitecturePPC64 == 6) { - determine_section_size(); - // TODO: PPC port } else { - // TODO: PPC port PdScheduling::power6SectorSize = 0x20; - } - if (PowerArchitecturePPC64 >= 8) { if (FLAG_IS_DEFAULT(SuperwordUseVSX)) { FLAG_SET_ERGO(SuperwordUseVSX, true); @@ -567,240 +561,6 @@ void VM_Version::print_features() { } } -#ifdef COMPILER2 -// Determine section size on power6: If section size is 8 instructions, -// there should be a difference between the two testloops of ~15 %. If -// no difference is detected the section is assumed to be 32 instructions. -void VM_Version::determine_section_size() { - - int unroll = 80; - - const int code_size = (2* unroll * 32 + 100)*BytesPerInstWord; - - // Allocate space for the code. - ResourceMark rm; - CodeBuffer cb("detect_section_size", code_size, 0); - MacroAssembler* a = new MacroAssembler(&cb); - - uint32_t *code = (uint32_t *)a->pc(); - // Emit code. - void (*test1)() = (void(*)())(void *)a->function_entry(); - - Label l1; - - a->li(R4, 1); - a->sldi(R4, R4, 28); - a->b(l1); - a->align(CodeEntryAlignment); - - a->bind(l1); - - for (int i = 0; i < unroll; i++) { - // Schleife 1 - // ------- sector 0 ------------ - // ;; 0 - a->nop(); // 1 - a->fpnop0(); // 2 - a->fpnop1(); // 3 - a->addi(R4,R4, -1); // 4 - - // ;; 1 - a->nop(); // 5 - a->fmr(F6, F6); // 6 - a->fmr(F7, F7); // 7 - a->endgroup(); // 8 - // ------- sector 8 ------------ - - // ;; 2 - a->nop(); // 9 - a->nop(); // 10 - a->fmr(F8, F8); // 11 - a->fmr(F9, F9); // 12 - - // ;; 3 - a->nop(); // 13 - a->fmr(F10, F10); // 14 - a->fmr(F11, F11); // 15 - a->endgroup(); // 16 - // -------- sector 16 ------------- - - // ;; 4 - a->nop(); // 17 - a->nop(); // 18 - a->fmr(F15, F15); // 19 - a->fmr(F16, F16); // 20 - - // ;; 5 - a->nop(); // 21 - a->fmr(F17, F17); // 22 - a->fmr(F18, F18); // 23 - a->endgroup(); // 24 - // ------- sector 24 ------------ - - // ;; 6 - a->nop(); // 25 - a->nop(); // 26 - a->fmr(F19, F19); // 27 - a->fmr(F20, F20); // 28 - - // ;; 7 - a->nop(); // 29 - a->fmr(F21, F21); // 30 - a->fmr(F22, F22); // 31 - a->brnop0(); // 32 - - // ------- sector 32 ------------ - } - - // ;; 8 - a->cmpdi(CCR0, R4, unroll); // 33 - a->bge(CCR0, l1); // 34 - a->blr(); - - // Emit code. - void (*test2)() = (void(*)())(void *)a->function_entry(); - // uint32_t *code = (uint32_t *)a->pc(); - - Label l2; - - a->li(R4, 1); - a->sldi(R4, R4, 28); - a->b(l2); - a->align(CodeEntryAlignment); - - a->bind(l2); - - for (int i = 0; i < unroll; i++) { - // Schleife 2 - // ------- sector 0 ------------ - // ;; 0 - a->brnop0(); // 1 - a->nop(); // 2 - //a->cmpdi(CCR0, R4, unroll); - a->fpnop0(); // 3 - a->fpnop1(); // 4 - a->addi(R4,R4, -1); // 5 - - // ;; 1 - - a->nop(); // 6 - a->fmr(F6, F6); // 7 - a->fmr(F7, F7); // 8 - // ------- sector 8 --------------- - - // ;; 2 - a->endgroup(); // 9 - - // ;; 3 - a->nop(); // 10 - a->nop(); // 11 - a->fmr(F8, F8); // 12 - - // ;; 4 - a->fmr(F9, F9); // 13 - a->nop(); // 14 - a->fmr(F10, F10); // 15 - - // ;; 5 - a->fmr(F11, F11); // 16 - // -------- sector 16 ------------- - - // ;; 6 - a->endgroup(); // 17 - - // ;; 7 - a->nop(); // 18 - a->nop(); // 19 - a->fmr(F15, F15); // 20 - - // ;; 8 - a->fmr(F16, F16); // 21 - a->nop(); // 22 - a->fmr(F17, F17); // 23 - - // ;; 9 - a->fmr(F18, F18); // 24 - // -------- sector 24 ------------- - - // ;; 10 - a->endgroup(); // 25 - - // ;; 11 - a->nop(); // 26 - a->nop(); // 27 - a->fmr(F19, F19); // 28 - - // ;; 12 - a->fmr(F20, F20); // 29 - a->nop(); // 30 - a->fmr(F21, F21); // 31 - - // ;; 13 - a->fmr(F22, F22); // 32 - } - - // -------- sector 32 ------------- - // ;; 14 - a->cmpdi(CCR0, R4, unroll); // 33 - a->bge(CCR0, l2); // 34 - - a->blr(); - uint32_t *code_end = (uint32_t *)a->pc(); - a->flush(); - - cb.insts()->set_end((u_char*)code_end); - - double loop1_seconds,loop2_seconds, rel_diff; - uint64_t start1, stop1; - - start1 = os::current_thread_cpu_time(false); - (*test1)(); - stop1 = os::current_thread_cpu_time(false); - loop1_seconds = (stop1- start1) / (1000 *1000 *1000.0); - - - start1 = os::current_thread_cpu_time(false); - (*test2)(); - stop1 = os::current_thread_cpu_time(false); - - loop2_seconds = (stop1 - start1) / (1000 *1000 *1000.0); - - rel_diff = (loop2_seconds - loop1_seconds) / loop1_seconds *100; - - if (PrintAssembly || PrintStubCode) { - ttyLocker ttyl; - tty->print_cr("Decoding section size detection stub at " INTPTR_FORMAT " before execution:", p2i(code)); - // Use existing decode function. This enables the [MachCode] format which is needed to DecodeErrorFile. - Disassembler::decode(&cb, (u_char*)code, (u_char*)code_end, tty); - tty->print_cr("Time loop1 :%f", loop1_seconds); - tty->print_cr("Time loop2 :%f", loop2_seconds); - tty->print_cr("(time2 - time1) / time1 = %f %%", rel_diff); - - if (rel_diff > 12.0) { - tty->print_cr("Section Size 8 Instructions"); - } else{ - tty->print_cr("Section Size 32 Instructions or Power5"); - } - } - -#if 0 // TODO: PPC port - // Set sector size (if not set explicitly). - if (FLAG_IS_DEFAULT(Power6SectorSize128PPC64)) { - if (rel_diff > 12.0) { - PdScheduling::power6SectorSize = 0x20; - } else { - PdScheduling::power6SectorSize = 0x80; - } - } else if (Power6SectorSize128PPC64) { - PdScheduling::power6SectorSize = 0x80; - } else { - PdScheduling::power6SectorSize = 0x20; - } -#endif - if (UsePower6SchedulerPPC64) Unimplemented(); -} -#endif // COMPILER2 - void VM_Version::determine_features() { #if defined(ABI_ELFv2) // 1 InstWord per call for the blr instruction. diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index fa94a71d992..984bfd0140d 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -84,8 +84,7 @@ class VM_Version: public Abstract_VM_Version { static void print_features(); static void determine_features(); // also measures cache line size static void config_dscr(); // Power 8: Configure Data Stream Control Register. - static void determine_section_size(); - static void power6_micro_bench(); + public: // Initialization static void initialize(); diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index 3c468e751d5..24c8178f1dc 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -1258,7 +1258,7 @@ void LIR_Assembler::emit_static_call_stub() { __ relocate(static_stub_Relocation::spec(call_pc)); - // See also Matcher::interpreter_method_oop_reg(). + // See also Matcher::interpreter_method_reg(). AddressLiteral meta = __ allocate_metadata_address(NULL); bool success = __ load_const_from_toc(Z_method, meta); diff --git a/src/hotspot/cpu/s390/globals_s390.hpp b/src/hotspot/cpu/s390/globals_s390.hpp index ac9e096ee64..d8f97b9c93b 100644 --- a/src/hotspot/cpu/s390/globals_s390.hpp +++ b/src/hotspot/cpu/s390/globals_s390.hpp @@ -75,13 +75,11 @@ define_pd_global(bool, CompactStrings, true); // 8146801 (Short Array Allocation): No performance work done here yet. define_pd_global(intx, InitArrayShortSize, 1*BytesPerLong); -#define ARCH_FLAGS(develop, \ - product, \ - diagnostic, \ - experimental, \ - notproduct, \ - range, \ - constraint) \ +#define ARCH_FLAGS(develop, \ + product, \ + notproduct, \ + range, \ + constraint) \ \ /* Reoptimize code-sequences of calls at runtime, e.g. replace an */ \ /* indirect call by a direct call. */ \ @@ -117,4 +115,6 @@ define_pd_global(intx, InitArrayShortSize, 1*BytesPerLong); product(bool, TraceTraps, false, "Trace all traps the signal handler" \ "handles.") +// end of ARCH_FLAGS + #endif // CPU_S390_GLOBALS_S390_HPP diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 4235d009e8d..bb98182d781 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -278,8 +278,8 @@ alloc_class chunk2( // information in this architecture description. // 1) reg_class inline_cache_reg (as defined in frame section) -// 2) reg_class compiler_method_oop_reg (as defined in frame section) -// 2) reg_class interpreter_method_oop_reg (as defined in frame section) +// 2) reg_class compiler_method_reg (as defined in frame section) +// 2) reg_class interpreter_method_reg (as defined in frame section) // 3) reg_class stack_slots(/* one chunk of stack-based "registers" */) // Integer Register Classes @@ -1569,11 +1569,6 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return ret_value; // Per default match rules are supported. } -int Matcher::regnum_to_fpu_offset(int regnum) { - ShouldNotReachHere(); - return regnum - 32; // The FP registers are in the second chunk. -} - const bool Matcher::has_predicated_vectors(void) { return false; } @@ -2456,9 +2451,6 @@ source %{ // Definition of frame structure and management information. frame %{ - // What direction does stack grow in (assumed to be same for native & Java). - stack_direction(TOWARDS_LOW); - // These two registers define part of the calling convention between // compiled code and the interpreter. @@ -2471,10 +2463,10 @@ frame %{ // interpreter_arg_ptr_reg(Z_R6); // Temporary in compiled entry-points - // compiler_method_oop_reg(Z_R1);//Z_R1_scratch + // compiler_method_reg(Z_R1);//Z_R1_scratch - // Method Oop Register when calling interpreter - interpreter_method_oop_reg(Z_R9);//Z_method + // Method Register when calling interpreter + interpreter_method_reg(Z_R9);//Z_method // Optional: name the operand used by cisc-spilling to access // [stack_pointer + offset]. @@ -3539,15 +3531,15 @@ operand inline_cache_regP(iRegP reg) %{ interface(REG_INTER); %} -operand compiler_method_oop_regP(iRegP reg) %{ - constraint(ALLOC_IN_RC(z_r1_RegP)); // compiler_method_oop_reg +operand compiler_method_regP(iRegP reg) %{ + constraint(ALLOC_IN_RC(z_r1_RegP)); // compiler_method_reg match(reg); format %{ %} interface(REG_INTER); %} -operand interpreter_method_oop_regP(iRegP reg) %{ - constraint(ALLOC_IN_RC(z_r9_regP)); // interpreter_method_oop_reg +operand interpreter_method_regP(iRegP reg) %{ + constraint(ALLOC_IN_RC(z_r9_regP)); // interpreter_method_reg match(reg); format %{ %} interface(REG_INTER); diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index 663b8d1dc44..3460a767fac 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -29,6 +29,7 @@ #include "compiler/disassembler.hpp" #include "code/compiledIC.hpp" #include "memory/resourceArea.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/vm_version.hpp" diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp index 808ed1ee404..d96ea768914 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,9 +128,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { LogTarget(Trace, nmethod, barrier) out; if (out.is_enabled()) { - Thread* thread = Thread::current(); - assert(thread->is_Java_thread(), "must be JavaThread"); - JavaThread* jth = (JavaThread*) thread; + JavaThread* jth = JavaThread::current(); ResourceMark mark; log_trace(nmethod, barrier)("deoptimize(nmethod: %p, return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p", nm, (address *) return_address_ptr, nm->is_osr_method(), jth, diff --git a/src/hotspot/cpu/x86/globals_x86.hpp b/src/hotspot/cpu/x86/globals_x86.hpp index 502eeb9a451..57acc05031c 100644 --- a/src/hotspot/cpu/x86/globals_x86.hpp +++ b/src/hotspot/cpu/x86/globals_x86.hpp @@ -89,13 +89,11 @@ define_pd_global(bool, PreserveFramePointer, false); define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); -#define ARCH_FLAGS(develop, \ - product, \ - diagnostic, \ - experimental, \ - notproduct, \ - range, \ - constraint) \ +#define ARCH_FLAGS(develop, \ + product, \ + notproduct, \ + range, \ + constraint) \ \ develop(bool, IEEEPrecision, true, \ "Enables IEEE precision (for INTEL only)") \ @@ -114,7 +112,7 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseCLMUL, false, \ "Control whether CLMUL instructions can be used on x86/x64") \ \ - diagnostic(bool, UseIncDec, true, \ + product(bool, UseIncDec, true, DIAGNOSTIC, \ "Use INC, DEC instructions on x86") \ \ product(bool, UseNewLongLShift, false, \ @@ -148,7 +146,7 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseRTMLocking, false, \ "Enable RTM lock eliding for inflated locks in compiled code") \ \ - experimental(bool, UseRTMForStackLocks, false, \ + product(bool, UseRTMForStackLocks, false, EXPERIMENTAL, \ "Enable RTM lock eliding for stack locks in compiled code") \ \ product(bool, UseRTMDeopt, false, \ @@ -158,33 +156,33 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); "Number of RTM retries on lock abort or busy") \ range(0, max_jint) \ \ - experimental(int, RTMSpinLoopCount, 100, \ + product(int, RTMSpinLoopCount, 100, EXPERIMENTAL, \ "Spin count for lock to become free before RTM retry") \ range(0, max_jint) \ \ - experimental(int, RTMAbortThreshold, 1000, \ + product(int, RTMAbortThreshold, 1000, EXPERIMENTAL, \ "Calculate abort ratio after this number of aborts") \ range(0, max_jint) \ \ - experimental(int, RTMLockingThreshold, 10000, \ + product(int, RTMLockingThreshold, 10000, EXPERIMENTAL, \ "Lock count at which to do RTM lock eliding without " \ "abort ratio calculation") \ range(0, max_jint) \ \ - experimental(int, RTMAbortRatio, 50, \ + product(int, RTMAbortRatio, 50, EXPERIMENTAL, \ "Lock abort ratio at which to stop use RTM lock eliding") \ range(0, 100) /* natural range */ \ \ - experimental(int, RTMTotalCountIncrRate, 64, \ + product(int, RTMTotalCountIncrRate, 64, EXPERIMENTAL, \ "Increment total RTM attempted lock count once every n times") \ range(1, max_jint) \ constraint(RTMTotalCountIncrRateConstraintFunc,AfterErgo) \ \ - experimental(intx, RTMLockingCalculationDelay, 0, \ + product(intx, RTMLockingCalculationDelay, 0, EXPERIMENTAL, \ "Number of milliseconds to wait before start calculating aborts " \ "for RTM locking") \ \ - experimental(bool, UseRTMXendForLockBusy, true, \ + product(bool, UseRTMXendForLockBusy, true, EXPERIMENTAL, \ "Use RTM Xend instead of Xabort when lock busy") \ \ /* assembler */ \ @@ -203,21 +201,23 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseBMI2Instructions, false, \ "Use BMI2 instructions") \ \ - diagnostic(bool, UseLibmIntrinsic, true, \ + product(bool, UseLibmIntrinsic, true, DIAGNOSTIC, \ "Use Libm Intrinsics") \ \ /* Minimum array size in bytes to use AVX512 intrinsics */ \ /* for copy, inflate and fill which don't bail out early based on any */ \ /* condition. When this value is set to zero compare operations like */ \ /* compare, vectorizedMismatch, compress can also use AVX512 intrinsics.*/\ - diagnostic(int, AVX3Threshold, 4096, \ + product(int, AVX3Threshold, 4096, DIAGNOSTIC, \ "Minimum array size in bytes to use AVX512 intrinsics" \ "for copy, inflate and fill. When this value is set as zero" \ "compare operations can also use AVX512 intrinsics.") \ range(0, max_jint) \ \ - diagnostic(bool, IntelJccErratumMitigation, true, \ + product(bool, IntelJccErratumMitigation, true, DIAGNOSTIC, \ "Turn off JVM mitigations related to Intel micro code " \ "mitigations for the Intel JCC erratum") +// end of ARCH_FLAGS + #endif // CPU_X86_GLOBALS_X86_HPP diff --git a/src/hotspot/cpu/x86/rdtsc_x86.cpp b/src/hotspot/cpu/x86/rdtsc_x86.cpp index 1fafbe1c68c..a4e743cc2df 100644 --- a/src/hotspot/cpu/x86/rdtsc_x86.cpp +++ b/src/hotspot/cpu/x86/rdtsc_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * 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,6 +24,7 @@ #include "precompiled.hpp" #include "rdtsc_x86.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/orderAccess.hpp" #include "runtime/thread.inline.hpp" #include "vm_version_ext_x86.hpp" diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 0fd3cc9b4f0..dd3bc57c9ac 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -29,6 +29,7 @@ #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 2fce29a52e4..5e61fd34c7b 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -27,7 +27,6 @@ #include "memory/universe.hpp" #include "runtime/abstract_vm_version.hpp" -#include "runtime/globals_extension.hpp" class VM_Version : public Abstract_VM_Version { friend class VMStructs; diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 4fccb028b5c..e572f3ca895 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -131,8 +131,8 @@ alloc_class chunk0( ECX, EBX, EBP, EDI, EAX, EDX, ESI, ESP, // Several register classes are automatically defined based upon information in // this architecture description. // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ ) -// 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ ) -// 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ ) +// 2) reg_class compiler_method_reg ( /* as def'd in frame section */ ) +// 2) reg_class interpreter_method_reg ( /* as def'd in frame section */ ) // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) // // Class for no registers (empty set). @@ -1371,10 +1371,6 @@ uint MachUEPNode::size(PhaseRegAlloc *ra_) const { //============================================================================= -int Matcher::regnum_to_fpu_offset(int regnum) { - return regnum - 32; // The FP registers are in the second chunk -} - // This is UltraSparc specific, true just means we have fast l2f conversion const bool Matcher::convL2FSupported(void) { return true; @@ -1931,7 +1927,7 @@ encode %{ // enc_class Java_Interpreter_Call (label labl) %{ // JAVA INTERPRETER CALL // // int ic_reg = Matcher::inline_cache_reg(); // // int ic_encode = Matcher::_regEncode[ic_reg]; -// // int imo_reg = Matcher::interpreter_method_oop_reg(); +// // int imo_reg = Matcher::interpreter_method_reg(); // // int imo_encode = Matcher::_regEncode[imo_reg]; // // // // Interpreter expects method_ptr in EBX, currently a callee-saved register, @@ -3191,13 +3187,10 @@ encode %{ // the region from SP to FP meets the minimum stack alignment. frame %{ - // What direction does stack grow in (assumed to be same for C & Java) - stack_direction(TOWARDS_LOW); - // These three registers define part of the calling convention // between compiled code and the interpreter. inline_cache_reg(EAX); // Inline Cache Register - interpreter_method_oop_reg(EBX); // Method Oop Register when calling interpreter + interpreter_method_reg(EBX); // Method Register when calling interpreter // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] cisc_spilling_operand_name(indOffset32); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index f26f6fa62b4..9664b4a3041 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -161,8 +161,8 @@ alloc_class chunk0(R10, R10_H, // Several register classes are automatically defined based upon information in // this architecture description. // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ ) -// 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ ) -// 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ ) +// 2) reg_class compiler_method_reg ( /* as def'd in frame section */ ) +// 2) reg_class interpreter_method_reg ( /* as def'd in frame section */ ) // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) // @@ -1578,11 +1578,6 @@ uint MachUEPNode::size(PhaseRegAlloc* ra_) const //============================================================================= -int Matcher::regnum_to_fpu_offset(int regnum) -{ - return regnum - 32; // The FP registers are in the second chunk -} - // This is UltraSparc specific, true just means we have fast l2f conversion const bool Matcher::convL2FSupported(void) { return true; @@ -2740,13 +2735,10 @@ encode %{ frame %{ - // What direction does stack grow in (assumed to be same for C & Java) - stack_direction(TOWARDS_LOW); - // These three registers define part of the calling convention // between compiled code and the interpreter. inline_cache_reg(RAX); // Inline Cache Register - interpreter_method_oop_reg(RBX); // Method Oop Register when + interpreter_method_reg(RBX); // Method Register when // calling interpreter // Optional: name the operand used by cisc-spilling to access diff --git a/src/hotspot/cpu/zero/frame_zero.cpp b/src/hotspot/cpu/zero/frame_zero.cpp index 0158812cc64..bd900de5741 100644 --- a/src/hotspot/cpu/zero/frame_zero.cpp +++ b/src/hotspot/cpu/zero/frame_zero.cpp @@ -94,7 +94,7 @@ void frame::patch_pc(Thread* thread, address pc) { // We borrow this call to set the thread pointer in the interpreter // state; the hook to set up deoptimized frames isn't supplied it. assert(pc == NULL, "should be"); - get_interpreterState()->set_thread((JavaThread *) thread); + get_interpreterState()->set_thread(thread->as_Java_thread()); } } diff --git a/src/hotspot/cpu/zero/globals_zero.hpp b/src/hotspot/cpu/zero/globals_zero.hpp index a05504eea3b..7028276a1d8 100644 --- a/src/hotspot/cpu/zero/globals_zero.hpp +++ b/src/hotspot/cpu/zero/globals_zero.hpp @@ -73,19 +73,18 @@ define_pd_global(bool, PreserveFramePointer, false); // No performance work done here yet. define_pd_global(bool, CompactStrings, false); -#define ARCH_FLAGS(develop, \ - product, \ - diagnostic, \ - experimental, \ - notproduct, \ - range, \ - constraint) \ +#define ARCH_FLAGS(develop, \ + product, \ + notproduct, \ + range, \ + constraint) \ \ product(bool, UseFastEmptyMethods, true, \ "Use fast method entry code for empty methods") \ \ product(bool, UseFastAccessorMethods, true, \ - "Use fast method entry code for accessor methods") \ - \ + "Use fast method entry code for accessor methods") + +// end of ARCH_FLAGS #endif // CPU_ZERO_GLOBALS_ZERO_HPP diff --git a/src/hotspot/cpu/zero/interpreterFrame_zero.hpp b/src/hotspot/cpu/zero/interpreterFrame_zero.hpp index 4e96d7b3481..a8066080d54 100644 --- a/src/hotspot/cpu/zero/interpreterFrame_zero.hpp +++ b/src/hotspot/cpu/zero/interpreterFrame_zero.hpp @@ -57,8 +57,8 @@ class InterpreterFrame : public ZeroFrame { protected: enum Layout { istate_off = jf_header_words + - (align_up_(sizeof(BytecodeInterpreter), - wordSize) >> LogBytesPerWord) - 1, + (align_up(sizeof(BytecodeInterpreter), + wordSize) >> LogBytesPerWord) - 1, header_words }; diff --git a/src/hotspot/cpu/zero/methodHandles_zero.cpp b/src/hotspot/cpu/zero/methodHandles_zero.cpp index a644a63251a..4929712d127 100644 --- a/src/hotspot/cpu/zero/methodHandles_zero.cpp +++ b/src/hotspot/cpu/zero/methodHandles_zero.cpp @@ -38,7 +38,7 @@ void MethodHandles::invoke_target(Method* method, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); @@ -55,7 +55,7 @@ void MethodHandles::invoke_target(Method* method, TRAPS) { oop MethodHandles::popFromStack(TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); intptr_t* topOfStack = istate->stack(); @@ -70,7 +70,7 @@ oop MethodHandles::popFromStack(TRAPS) { void MethodHandles::throw_AME(Klass* rcvr, Method* interface_method, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); // Set up the frame anchor if it isn't already bool has_last_Java_frame = thread->has_last_Java_frame(); if (!has_last_Java_frame) { @@ -101,7 +101,7 @@ void MethodHandles::throw_AME(Klass* rcvr, Method* interface_method, TRAPS) { int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); intptr_t* topOfStack = istate->stack(); @@ -132,7 +132,7 @@ int MethodHandles::method_handle_entry_linkToStaticOrSpecial(Method* method, int } int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t UNUSED, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); @@ -172,7 +172,7 @@ int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t } int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); diff --git a/src/hotspot/cpu/zero/stack_zero.cpp b/src/hotspot/cpu/zero/stack_zero.cpp index 11a5c636a53..ee61f2d2f2b 100644 --- a/src/hotspot/cpu/zero/stack_zero.cpp +++ b/src/hotspot/cpu/zero/stack_zero.cpp @@ -46,7 +46,7 @@ int ZeroStack::suggest_size(Thread *thread) const { } void ZeroStack::handle_overflow(TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); // Set up the frame anchor if it isn't already bool has_last_Java_frame = thread->has_last_Java_frame(); diff --git a/src/hotspot/cpu/zero/stubGenerator_zero.cpp b/src/hotspot/cpu/zero/stubGenerator_zero.cpp index a290eef2021..d0513de976e 100644 --- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp +++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010, 2015 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -72,7 +72,7 @@ class StubGenerator: public StubCodeGenerator { intptr_t* parameters, int parameter_words, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); // Make sure we have no pending exceptions @@ -316,7 +316,7 @@ EntryFrame *EntryFrame::build(const intptr_t* parameters, JavaCallWrapper* call_wrapper, TRAPS) { - ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack(); + ZeroStack *stack = THREAD->as_Java_thread()->zero_stack(); stack->overflow_check(header_words + parameter_words, CHECK_NULL); stack->push(0); // next_frame, filled in later diff --git a/src/hotspot/cpu/zero/vm_version_zero.cpp b/src/hotspot/cpu/zero/vm_version_zero.cpp index 6f8519aba53..bc38c7d81cf 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.cpp +++ b/src/hotspot/cpu/zero/vm_version_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "assembler_zero.inline.hpp" #include "memory/resourceArea.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/vm_version.hpp" diff --git a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp index 40f8b5f1840..9aae3e751e5 100644 --- a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp +++ b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp @@ -106,7 +106,7 @@ InterpreterCodelet* ZeroInterpreter::codelet_containing(address pc) { fixup_after_potential_safepoint() int ZeroInterpreter::normal_entry(Method* method, intptr_t UNUSED, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); // Allocate and initialize our frame. InterpreterFrame *frame = InterpreterFrame::build(method, CHECK_0); @@ -144,7 +144,7 @@ intptr_t narrow(BasicType type, intptr_t result) { void ZeroInterpreter::main_loop(int recurse, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); // If we are entering from a deopt we may need to call @@ -277,7 +277,7 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { // Make sure method is native and not abstract assert(method->is_native() && !method->is_abstract(), "should be"); - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); // Allocate and initialize our frame @@ -546,7 +546,7 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { } int ZeroInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); intptr_t *locals = stack->sp(); @@ -679,7 +679,7 @@ int ZeroInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { } int ZeroInterpreter::empty_entry(Method* method, intptr_t UNUSED, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); // Drop into the slow path if we need a safepoint check @@ -698,7 +698,7 @@ int ZeroInterpreter::empty_entry(Method* method, intptr_t UNUSED, TRAPS) { // Slots < insert_before will have the same slot number after the insert. // Slots >= insert_before will become old_slot + num_slots. void ZeroInterpreter::insert_vmslots(int insert_before, int num_slots, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); // Allocate the space @@ -712,7 +712,7 @@ void ZeroInterpreter::insert_vmslots(int insert_before, int num_slots, TRAPS) { } void ZeroInterpreter::remove_vmslots(int first_slot, int num_slots, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); intptr_t *vmslots = stack->sp(); @@ -745,7 +745,7 @@ JRT_ENTRY(void, ZeroInterpreter::throw_exception(JavaThread* thread, JRT_END InterpreterFrame *InterpreterFrame::build(Method* const method, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; + JavaThread *thread = THREAD->as_Java_thread(); ZeroStack *stack = thread->zero_stack(); // Calculate the size of the frame we'll build, including @@ -821,7 +821,7 @@ InterpreterFrame *InterpreterFrame::build(Method* const method, TRAPS) { } InterpreterFrame *InterpreterFrame::build(int size, TRAPS) { - ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack(); + ZeroStack *stack = THREAD->as_Java_thread()->zero_stack(); int size_in_words = size >> LogBytesPerWord; assert(size_in_words * wordSize == size, "unaligned"); diff --git a/src/hotspot/os/aix/globals_aix.hpp b/src/hotspot/os/aix/globals_aix.hpp index 1c434b5d976..b6b67a4f3bb 100644 --- a/src/hotspot/os/aix/globals_aix.hpp +++ b/src/hotspot/os/aix/globals_aix.hpp @@ -27,18 +27,16 @@ #define OS_AIX_GLOBALS_AIX_HPP // -// Defines Aix specific flags. They are not available on other platforms. +// Declare Aix specific flags. They are not available on other platforms. // // (Please keep the switches sorted alphabetically.) -#define RUNTIME_OS_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - notproduct, \ - range, \ - constraint) \ +#define RUNTIME_OS_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ \ /* Whether to allow the VM to run if EXTSHM=ON. EXTSHM is an environment */ \ /* variable used on AIX to activate certain hacks which allow more shm segments */\ @@ -77,9 +75,9 @@ /* explicit commit behaviour. This flag, if true, causes the VM to touch */ \ /* memory on os::commit_memory() (which normally is a noop). */ \ product(bool, UseExplicitCommit, false, \ - "Explicit commit for virtual memory.") \ - \ + "Explicit commit for virtual memory.") +// end of RUNTIME_OS_FLAGS // // Defines Aix-specific default values. The flags are available on all diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 64face5268a..43e7f292421 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -54,6 +54,7 @@ #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/hotspot/os/bsd/globals_bsd.hpp b/src/hotspot/os/bsd/globals_bsd.hpp index 344a04d63c3..6c8939a6dc0 100644 --- a/src/hotspot/os/bsd/globals_bsd.hpp +++ b/src/hotspot/os/bsd/globals_bsd.hpp @@ -26,18 +26,18 @@ #define OS_BSD_GLOBALS_BSD_HPP // -// Defines Bsd specific flags. They are not available on other platforms. +// Declare Bsd specific flags. They are not available on other platforms. // -#define RUNTIME_OS_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - notproduct, \ - range, \ +#define RUNTIME_OS_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ constraint) +// end of RUNTIME_OS_FLAGS + // // Defines Bsd-specific default values. The flags are available on all // platforms, but they may have different default values on other platforms. diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 943133e27e5..1a8f0a4558e 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -45,6 +45,7 @@ #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/hotspot/os/linux/globals_linux.hpp b/src/hotspot/os/linux/globals_linux.hpp index 2baf2b805dc..f2a889285af 100644 --- a/src/hotspot/os/linux/globals_linux.hpp +++ b/src/hotspot/os/linux/globals_linux.hpp @@ -26,17 +26,15 @@ #define OS_LINUX_GLOBALS_LINUX_HPP // -// Defines Linux specific flags. They are not available on other platforms. +// Declare Linux specific flags. They are not available on other platforms. // -#define RUNTIME_OS_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - notproduct, \ - range, \ - constraint) \ +#define RUNTIME_OS_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ \ product(bool, UseOprofile, false, \ "enable support for Oprofile profiler") \ @@ -70,19 +68,21 @@ "Increase the thread stack size to include space for glibc " \ "static thread-local storage (TLS) if true") \ \ - diagnostic(bool, DumpPrivateMappingsInCore, true, \ + product(bool, DumpPrivateMappingsInCore, true, DIAGNOSTIC, \ "If true, sets bit 2 of /proc/PID/coredump_filter, thus " \ "resulting in file-backed private mappings of the process to "\ "be dumped into the corefile.") \ \ - diagnostic(bool, DumpSharedMappingsInCore, true, \ + product(bool, DumpSharedMappingsInCore, true, DIAGNOSTIC, \ "If true, sets bit 3 of /proc/PID/coredump_filter, thus " \ "resulting in file-backed shared mappings of the process to " \ "be dumped into the corefile.") \ \ - diagnostic(bool, UseCpuAllocPath, false, \ + product(bool, UseCpuAllocPath, false, DIAGNOSTIC, \ "Use CPU_ALLOC code path in os::active_processor_count ") +// end of RUNTIME_OS_FLAGS + // // Defines Linux-specific default values. The flags are available on all // platforms, but they may have different default values on other platforms. diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index e3a9cfa386b..5c610cdf7e9 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -46,6 +46,7 @@ #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/init.hpp" #include "runtime/java.hpp" @@ -1040,13 +1041,12 @@ bool os::create_attached_thread(JavaThread* thread) { // enabling yellow zone first will crash JVM on SuSE Linux), so there // is no gap between the last two virtual memory regions. - JavaThread *jt = (JavaThread *)thread; - address addr = jt->stack_reserved_zone_base(); + address addr = thread->stack_reserved_zone_base(); assert(addr != NULL, "initialization problem?"); - assert(jt->stack_available(addr) > 0, "stack guard should not be enabled"); + assert(thread->stack_available(addr) > 0, "stack guard should not be enabled"); osthread->set_expanding_stack(); - os::Linux::manually_expand_stack(jt, addr); + os::Linux::manually_expand_stack(thread, addr); osthread->clear_expanding_stack(); } @@ -1781,7 +1781,6 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { "'execstack -c <libfile>', or link it with '-z noexecstack'.", filename); - assert(Thread::current()->is_Java_thread(), "must be Java thread"); JavaThread *jt = JavaThread::current(); if (jt->thread_state() != _thread_in_native) { // This happens when a compiler thread tries to load a hsdis-<arch>.so file diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 40ed3d877c2..39d2d2732ad 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -26,6 +26,7 @@ #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "os_posix.inline.hpp" +#include "runtime/globals_extension.hpp" #include "utilities/globalDefinitions.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" @@ -2073,9 +2074,7 @@ void Parker::park(bool isAbsolute, jlong time) { // since we are doing a lock-free update to _counter. if (Atomic::xchg(&_counter, 0) > 0) return; - Thread* thread = Thread::current(); - assert(thread->is_Java_thread(), "Must be JavaThread"); - JavaThread *jt = (JavaThread *)thread; + JavaThread *jt = JavaThread::current(); // Optional optimization -- avoid state transitions if there's // an interrupt pending. @@ -2120,7 +2119,7 @@ void Parker::park(bool isAbsolute, jlong time) { return; } - OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); + OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); jt->set_suspend_equivalent(); // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() diff --git a/src/hotspot/os/windows/globals_windows.hpp b/src/hotspot/os/windows/globals_windows.hpp index f91951097c9..a712e102a76 100644 --- a/src/hotspot/os/windows/globals_windows.hpp +++ b/src/hotspot/os/windows/globals_windows.hpp @@ -26,18 +26,18 @@ #define OS_WINDOWS_GLOBALS_WINDOWS_HPP // -// Defines Windows specific flags. They are not available on other platforms. +// Declare Windows specific flags. They are not available on other platforms. // -#define RUNTIME_OS_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - notproduct, \ - range, \ +#define RUNTIME_OS_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ constraint) +// end of RUNTIME_OS_FLAGS + // // Defines Windows-specific default values. The flags are available on all diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index fd85dddc556..99ed8f22db0 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -48,6 +48,7 @@ #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -2136,19 +2137,19 @@ int os::signal_wait() { LONG Handle_Exception(struct _EXCEPTION_POINTERS* exceptionInfo, address handler) { - JavaThread* thread = (JavaThread*) Thread::current_or_null(); + Thread* thread = Thread::current_or_null(); // Save pc in thread #ifdef _M_AMD64 // Do not blow up if no thread info available. - if (thread) { - thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip); + if (thread != NULL) { + thread->as_Java_thread()->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip); } // Set pc to handler exceptionInfo->ContextRecord->Rip = (DWORD64)handler; #else // Do not blow up if no thread info available. - if (thread) { - thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip); + if (thread != NULL) { + thread->as_Java_thread()->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip); } // Set pc to handler exceptionInfo->ContextRecord->Eip = (DWORD)(DWORD_PTR)handler; @@ -2477,7 +2478,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } if (t != NULL && t->is_Java_thread()) { - JavaThread* thread = (JavaThread*) t; + JavaThread* thread = t->as_Java_thread(); bool in_java = thread->thread_state() == _thread_in_Java; bool in_native = thread->thread_state() == _thread_in_native; bool in_vm = thread->thread_state() == _thread_in_vm; @@ -2570,7 +2571,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (exception_code == EXCEPTION_IN_PAGE_ERROR) { CompiledMethod* nm = NULL; - JavaThread* thread = (JavaThread*)t; if (in_java) { CodeBlob* cb = CodeCache::find_blob_unsafe(pc); nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index e5e4bbc434e..f22a7390d28 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -228,7 +228,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec if (os::Aix::signal_handlers_are_installed) { if (t != NULL) { if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()) { vmthread = (VMThread *)t; diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index fd616151715..c2437d56350 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -457,7 +457,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::signal_handlers_are_installed) { if (t != NULL ){ if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()){ vmthread = (VMThread *)t; diff --git a/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp index 3522cad9e1f..3d7dc7e4b5a 100644 --- a/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp @@ -46,13 +46,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -77,11 +74,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } frame ret_frame(ret_sp, ret_fp, addr); - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp index 4db293eca15..b404c840a6a 100644 --- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp +++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp @@ -156,7 +156,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::signal_handlers_are_installed) { if (t != NULL ){ if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()){ vmthread = (VMThread *)t; diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index 0075e7e841c..18651ae81b1 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -237,7 +237,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::signal_handlers_are_installed) { if (t != NULL ){ if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()){ vmthread = (VMThread *)t; diff --git a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp index c09244ed754..799d2cf87d1 100644 --- a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp @@ -47,13 +47,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -78,10 +75,10 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } frame ret_frame(ret_sp, ret_fp, addr); - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #ifdef COMPILER2 frame ret_frame2(ret_sp, NULL, addr); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } @@ -100,4 +97,3 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } void JavaThread::cache_global_variables() { } - diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index eb54fd091da..a04f79a4eae 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -296,7 +296,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info, if (os::Linux::signal_handlers_are_installed) { if (t != NULL ){ if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()){ vmthread = (VMThread *)t; diff --git a/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp index 8776e9198bc..6fd8a2fbde5 100644 --- a/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp @@ -74,20 +74,16 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); - - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. - if (jt->has_last_Java_frame()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame()) { + *fr_addr = pd_last_frame(); return true; } // Could be in a code section that plays with the stack, like // MacroAssembler::verify_heapbase() - if (jt->in_top_frame_unsafe_section()) { + if (in_top_frame_unsafe_section()) { return false; } @@ -112,11 +108,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } frame ret_frame(ret_sp, ret_fp, addr); - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #ifdef COMPILER2 // C2 uses ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index 0f5251df602..c747ba12d64 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -280,7 +280,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::signal_handlers_are_installed) { if (t != NULL) { if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()) { vmthread = (VMThread *)t; } diff --git a/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp index ca7c68f646b..f853f7a439a 100644 --- a/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -42,7 +42,6 @@ frame JavaThread::pd_last_frame() { } bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index e803c6fdce8..0d3a36f94ce 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp @@ -280,7 +280,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::signal_handlers_are_installed) { if (t != NULL) { if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()) { vmthread = (VMThread *)t; } diff --git a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp index 4f14f9969f7..aebadb25518 100644 --- a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp @@ -42,7 +42,6 @@ frame JavaThread::pd_last_frame() { } bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index 37eb6db2e83..598383ca9db 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -276,7 +276,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::signal_handlers_are_installed) { if (t != NULL ){ if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()){ vmthread = (VMThread *)t; diff --git a/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp index f2e5ef10310..b72127907b2 100644 --- a/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp @@ -47,13 +47,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -78,11 +75,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } frame ret_frame(ret_sp, ret_fp, addr); - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } @@ -101,4 +98,3 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } void JavaThread::cache_global_variables() { } - diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp index d9e2382bf2c..e2de18263f0 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp @@ -152,7 +152,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::signal_handlers_are_installed) { if (t != NULL ){ if(t->is_Java_thread()) { - thread = (JavaThread*)t; + thread = t->as_Java_thread(); } else if(t->is_VM_thread()){ vmthread = (VMThread *)t; diff --git a/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp index a1f0ff39150..048574596f4 100644 --- a/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp @@ -47,15 +47,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - - assert(this->is_Java_thread(), "must be JavaThread"); - - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than CONTEXT info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -75,11 +70,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_frame.sp(), NULL, ret_frame.pc()); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } diff --git a/src/hotspot/share/adlc/adlparse.cpp b/src/hotspot/share/adlc/adlparse.cpp index 547b378c466..198ee4eb586 100644 --- a/src/hotspot/share/adlc/adlparse.cpp +++ b/src/hotspot/share/adlc/adlparse.cpp @@ -985,9 +985,6 @@ void ADLParser::frame_parse(void) { parse_err(SYNERR, "missing identifier inside frame block.\n"); return; } - if (strcmp(token,"stack_direction")==0) { - stack_dir_parse(frame); - } if (strcmp(token,"sync_stack_slots")==0) { sync_stack_slots_parse(frame); } @@ -1005,7 +1002,11 @@ void ADLParser::frame_parse(void) { skipws(); } if (strcmp(token,"interpreter_method_oop_reg")==0) { - interpreter_method_oop_parse(frame, false); + parse_err(WARN, "Using obsolete Token, interpreter_method_oop_reg"); + skipws(); + } + if (strcmp(token,"interpreter_method_reg")==0) { + interpreter_method_parse(frame, false); } if (strcmp(token,"cisc_spilling_operand_name")==0) { cisc_spilling_operand_name_parse(frame, false); @@ -1109,21 +1110,6 @@ void ADLParser::frame_parse(void) { // skipws(); } -//------------------------------stack_dir_parse-------------------------------- -void ADLParser::stack_dir_parse(FrameForm *frame) { - char *direction = parse_one_arg("stack direction entry"); - if (strcmp(direction, "TOWARDS_LOW") == 0) { - frame->_direction = false; - } - else if (strcmp(direction, "TOWARDS_HIGH") == 0) { - frame->_direction = true; - } - else { - parse_err(SYNERR, "invalid value inside stack direction entry.\n"); - return; - } -} - //------------------------------sync_stack_slots_parse------------------------- void ADLParser::sync_stack_slots_parse(FrameForm *frame) { // Assign value into frame form @@ -1148,9 +1134,9 @@ void ADLParser::inline_cache_parse(FrameForm *frame, bool native) { frame->_inline_cache_reg = parse_one_arg("inline cache reg entry"); } -//------------------------------interpreter_method_oop_parse------------------ -void ADLParser::interpreter_method_oop_parse(FrameForm *frame, bool native) { - frame->_interpreter_method_oop_reg = parse_one_arg("method reg entry"); +//------------------------------interpreter_method_parse------------------ +void ADLParser::interpreter_method_parse(FrameForm *frame, bool native) { + frame->_interpreter_method_reg = parse_one_arg("method reg entry"); } //------------------------------cisc_spilling_operand_parse--------------------- diff --git a/src/hotspot/share/adlc/adlparse.hpp b/src/hotspot/share/adlc/adlparse.hpp index b1d27bd50d1..f73c3a5c365 100644 --- a/src/hotspot/share/adlc/adlparse.hpp +++ b/src/hotspot/share/adlc/adlparse.hpp @@ -110,13 +110,12 @@ class ADLParser { void enc_class_parse_block(EncClass* encoding, char* ec_name); // Parse the components of the frame section - void stack_dir_parse(FrameForm *frame); // Parse the stack direction entry void sync_stack_slots_parse(FrameForm *frame); void frame_pointer_parse(FrameForm *frame, bool native); void interpreter_frame_pointer_parse(FrameForm *frame, bool native); void inline_cache_parse(FrameForm *frame, bool native); void interpreter_arg_ptr_parse(FrameForm *frame, bool native); - void interpreter_method_oop_parse(FrameForm *frame, bool native); + void interpreter_method_parse(FrameForm *frame, bool native); void cisc_spilling_operand_name_parse(FrameForm *frame, bool native); void stack_alignment_parse(FrameForm *frame); void return_addr_parse(FrameForm *frame, bool native); diff --git a/src/hotspot/share/adlc/formsopt.hpp b/src/hotspot/share/adlc/formsopt.hpp index 7051c8909ea..0ee97160e3a 100644 --- a/src/hotspot/share/adlc/formsopt.hpp +++ b/src/hotspot/share/adlc/formsopt.hpp @@ -334,10 +334,9 @@ class FrameForm : public Form { public: // Public Data - bool _direction; // Direction of stack growth char *_sync_stack_slots; char *_inline_cache_reg; - char *_interpreter_method_oop_reg; + char *_interpreter_method_reg; char *_interpreter_frame_pointer_reg; char *_cisc_spilling_operand_name; char *_frame_pointer; diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp index 5c4dafb6c11..674748dd1aa 100644 --- a/src/hotspot/share/adlc/output_c.cpp +++ b/src/hotspot/share/adlc/output_c.cpp @@ -4143,9 +4143,6 @@ void ArchDesc::buildInstructMatchCheck(FILE *fp_cpp) const { // Output the methods to Matcher which specify frame behavior void ArchDesc::buildFrameMethods(FILE *fp_cpp) { fprintf(fp_cpp,"\n\n"); - // Stack Direction - fprintf(fp_cpp,"bool Matcher::stack_direction() const { return %s; }\n\n", - _frame->_direction ? "true" : "false"); // Sync Stack Slots fprintf(fp_cpp,"int Compile::sync_stack_slots() const { return %s; }\n\n", _frame->_sync_stack_slots); @@ -4195,12 +4192,12 @@ void ArchDesc::buildFrameMethods(FILE *fp_cpp) { fprintf(fp_cpp,"int Matcher::inline_cache_reg_encode() {"); fprintf(fp_cpp," return _regEncode[inline_cache_reg()]; }\n\n"); - // Interpreter's Method Oop Register, mask definition, and encoding - fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_method_oop_reg() {"); + // Interpreter's Method Register, mask definition, and encoding + fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_method_reg() {"); fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", - _frame->_interpreter_method_oop_reg); - fprintf(fp_cpp,"int Matcher::interpreter_method_oop_reg_encode() {"); - fprintf(fp_cpp," return _regEncode[interpreter_method_oop_reg()]; }\n\n"); + _frame->_interpreter_method_reg); + fprintf(fp_cpp,"int Matcher::interpreter_method_reg_encode() {"); + fprintf(fp_cpp," return _regEncode[interpreter_method_reg()]; }\n\n"); // Interpreter's Frame Pointer Register, mask definition, and encoding fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_frame_pointer_reg() {"); diff --git a/src/hotspot/share/aot/aotLoader.cpp b/src/hotspot/share/aot/aotLoader.cpp index 59dd56ab8fc..d1150589b97 100644 --- a/src/hotspot/share/aot/aotLoader.cpp +++ b/src/hotspot/share/aot/aotLoader.cpp @@ -31,6 +31,7 @@ #include "oops/compressedOops.hpp" #include "oops/method.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/os.inline.hpp" #include "runtime/timerTrace.hpp" diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index 51801875565..4c32940bc3e 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -32,17 +32,15 @@ #include OS_HEADER(c1_globals) // -// Defines all global flags used by the client compiler. +// Declare all global flags used by the client compiler. // -#define C1_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - notproduct, \ - range, \ - constraint) \ +#define C1_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ \ /* Printing */ \ notproduct(bool, PrintC1Statistics, false, \ @@ -158,7 +156,7 @@ product(bool, InlineSynchronizedMethods, true, \ "Inline synchronized methods") \ \ - diagnostic(bool, InlineNIOCheckIndex, true, \ + product(bool, InlineNIOCheckIndex, true, DIAGNOSTIC, \ "Intrinsify java.nio.Buffer.checkIndex") \ \ develop(bool, CanonicalizeNodes, true, \ @@ -337,7 +335,8 @@ "Update MethodData*s in Tier1-generated code") \ \ develop(bool, PrintCFGToFile, false, \ - "print control flow graph to a separate file during compilation") \ - \ + "print control flow graph to a separate file during compilation") + +// end of C1_FLAGS #endif // SHARE_C1_C1_GLOBALS_HPP diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index bd178fd2046..9eeeea27f0d 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -453,10 +453,10 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, Klass* kls; if (!require_local) { kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, - KILL_COMPILE_ON_FATAL_(fail_type)); + CHECK_AND_CLEAR_(fail_type)); } else { kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, - KILL_COMPILE_ON_FATAL_(fail_type)); + CHECK_AND_CLEAR_(fail_type)); } found_klass = kls; } diff --git a/src/hotspot/share/ci/ciField.cpp b/src/hotspot/share/ci/ciField.cpp index 23ba2f1ba60..df4dfc9ae63 100644 --- a/src/hotspot/share/ci/ciField.cpp +++ b/src/hotspot/share/ci/ciField.cpp @@ -400,7 +400,7 @@ bool ciField::will_link(ciMethod* accessing_method, _name->get_symbol(), _signature->get_symbol(), methodHandle(THREAD, accessing_method->get_Method())); fieldDescriptor result; - LinkResolver::resolve_field(result, link_info, bc, false, KILL_COMPILE_ON_FATAL_(false)); + LinkResolver::resolve_field(result, link_info, bc, false, CHECK_AND_CLEAR_(false)); // update the hit-cache, unless there is a problem with memory scoping: if (accessing_method->holder()->is_shared() || !is_shared()) { diff --git a/src/hotspot/share/ci/ciMethod.cpp b/src/hotspot/share/ci/ciMethod.cpp index ac9293dbb01..3fc9a0f6ebd 100644 --- a/src/hotspot/share/ci/ciMethod.cpp +++ b/src/hotspot/share/ci/ciMethod.cpp @@ -1241,7 +1241,7 @@ bool ciMethod::has_unloaded_classes_in_signature() { { EXCEPTION_MARK; methodHandle m(THREAD, get_Method()); - bool has_unloaded = Method::has_unloaded_classes_in_signature(m, (JavaThread *)THREAD); + bool has_unloaded = Method::has_unloaded_classes_in_signature(m, thread); if( HAS_PENDING_EXCEPTION ) { CLEAR_PENDING_EXCEPTION; return true; // Declare that we may have unloaded classes diff --git a/src/hotspot/share/ci/ciReplay.cpp b/src/hotspot/share/ci/ciReplay.cpp index 5939966b330..b9fec53b08b 100644 --- a/src/hotspot/share/ci/ciReplay.cpp +++ b/src/hotspot/share/ci/ciReplay.cpp @@ -38,6 +38,7 @@ #include "oops/method.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/fieldDescriptor.inline.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "utilities/copy.hpp" diff --git a/src/hotspot/share/ci/ciUtilities.inline.hpp b/src/hotspot/share/ci/ciUtilities.inline.hpp index 5c6293145a4..8b752cd812a 100644 --- a/src/hotspot/share/ci/ciUtilities.inline.hpp +++ b/src/hotspot/share/ci/ciUtilities.inline.hpp @@ -66,27 +66,4 @@ #define GUARDED_VM_QUICK_ENTRY(action) \ {if (IS_IN_VM) { action } else { VM_QUICK_ENTRY_MARK; { action }}} -// Redefine this later. -#define KILL_COMPILE_ON_FATAL_(result) \ - THREAD); \ - if (HAS_PENDING_EXCEPTION) { \ - if (PENDING_EXCEPTION->klass() == \ - SystemDictionary::ThreadDeath_klass()) { \ - /* Kill the compilation. */ \ - fatal("unhandled ci exception"); \ - return (result); \ - } \ - CLEAR_PENDING_EXCEPTION; \ - return (result); \ - } \ - (void)(0 - -#define KILL_COMPILE_ON_ANY \ - THREAD); \ - if (HAS_PENDING_EXCEPTION) { \ - fatal("unhandled ci exception"); \ - CLEAR_PENDING_EXCEPTION; \ - } \ -(void)(0 - #endif // SHARE_CI_CIUTILITIES_INLINE_HPP diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 7c1f51e1f34..7b34ef939c5 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -1644,12 +1644,14 @@ void ClassLoader::create_javabase() { { MutexLocker ml(THREAD, Module_lock); - ModuleEntry* jb_module = null_cld_modules->locked_create_entry(Handle(), + if (ModuleEntryTable::javabase_moduleEntry() == NULL) { // may have been inited by CDS. + ModuleEntry* jb_module = null_cld_modules->locked_create_entry(Handle(), false, vmSymbols::java_base(), NULL, NULL, null_cld); - if (jb_module == NULL) { - vm_exit_during_initialization("Unable to create ModuleEntry for " JAVA_BASE_NAME); + if (jb_module == NULL) { + vm_exit_during_initialization("Unable to create ModuleEntry for " JAVA_BASE_NAME); + } + ModuleEntryTable::set_javabase_moduleEntry(jb_module); } - ModuleEntryTable::set_javabase_moduleEntry(jb_module); } } diff --git a/src/hotspot/share/classfile/classLoaderDataShared.cpp b/src/hotspot/share/classfile/classLoaderDataShared.cpp new file mode 100644 index 00000000000..da562f52d50 --- /dev/null +++ b/src/hotspot/share/classfile/classLoaderDataShared.cpp @@ -0,0 +1,202 @@ + /* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/classLoaderData.inline.hpp" +#include "classfile/classLoaderDataShared.hpp" +#include "classfile/moduleEntry.hpp" +#include "classfile/packageEntry.hpp" +#include "logging/log.hpp" +#include "memory/metaspaceShared.hpp" +#include "runtime/handles.inline.hpp" + +#if INCLUDE_CDS_JAVA_HEAP + +class ArchivedClassLoaderData { + Array<PackageEntry*>* _packages; + Array<ModuleEntry*>* _modules; + + void assert_valid(ClassLoaderData* loader_data) { + // loader_data may be NULL if the boot layer has loaded no modules for the platform or + // system loaders (e.g., if you create a custom JDK image with only java.base). + if (loader_data != NULL) { + assert(!loader_data->has_class_mirror_holder(), + "loaders for non-strong hidden classes or unsafe anonymous classes not supported"); + } + } +public: + ArchivedClassLoaderData() : _packages(NULL), _modules(NULL) {} + + void iterate_symbols(ClassLoaderData* loader_data, MetaspaceClosure* closure); + void allocate(ClassLoaderData* loader_data); + void init_archived_entries(ClassLoaderData* loader_data); + void init_archived_oops(ClassLoaderData* loader_data); + + void serialize(SerializeClosure* f) { + f->do_ptr((void**)&_packages); + f->do_ptr((void**)&_modules); + } + + void restore(ClassLoaderData* loader_data, bool do_entries, bool do_oops); +}; + +static ArchivedClassLoaderData _archived_boot_loader_data; +static ArchivedClassLoaderData _archived_platform_loader_data; +static ArchivedClassLoaderData _archived_system_loader_data; +static ModuleEntry* _archived_javabase_moduleEntry = NULL; + +void ArchivedClassLoaderData::iterate_symbols(ClassLoaderData* loader_data, MetaspaceClosure* closure) { + assert(DumpSharedSpaces, "must be"); + assert_valid(loader_data); + if (loader_data != NULL) { + loader_data->packages()->iterate_symbols(closure); + loader_data->modules() ->iterate_symbols(closure); + } +} + +void ArchivedClassLoaderData::allocate(ClassLoaderData* loader_data) { + assert(DumpSharedSpaces, "must be"); + assert_valid(loader_data); + if (loader_data != NULL) { + // We can't create hashtables at dump time because the hashcode depends on the + // address of the Symbols, which may be relocated at runtime due to ASLR. + // So we store the packages/modules in Arrays. At runtime, we create + // the hashtables using these arrays. + _packages = loader_data->packages()->allocate_archived_entries(); + _modules = loader_data->modules() ->allocate_archived_entries(); + } +} + +void ArchivedClassLoaderData::init_archived_entries(ClassLoaderData* loader_data) { + assert(DumpSharedSpaces, "must be"); + assert_valid(loader_data); + if (loader_data != NULL) { + loader_data->packages()->init_archived_entries(_packages); + loader_data->modules() ->init_archived_entries(_modules); + } +} + +void ArchivedClassLoaderData::init_archived_oops(ClassLoaderData* loader_data) { + assert(DumpSharedSpaces, "must be"); + assert_valid(loader_data); + if (loader_data != NULL) { + loader_data->modules()->init_archived_oops(_modules); + } +} + +void ArchivedClassLoaderData::restore(ClassLoaderData* loader_data, bool do_entries, bool do_oops) { + assert(UseSharedSpaces, "must be"); + assert_valid(loader_data); + if (_modules != NULL) { // Could be NULL if we have archived no modules for platform/system loaders + ModuleEntryTable* modules = loader_data->modules(); + PackageEntryTable* packages = loader_data->packages(); + + MutexLocker m1(Module_lock); + if (do_entries) { + modules->load_archived_entries(loader_data, _modules); + packages->load_archived_entries(_packages); + } + if (do_oops) { + modules->restore_archived_oops(loader_data, _modules); + } + } +} + +// ------------------------------ + +static ClassLoaderData* null_class_loader_data() { + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + assert(loader_data != NULL, "must be"); + return loader_data; +} + +static ClassLoaderData* java_platform_loader_data_or_null() { + return ClassLoaderData::class_loader_data_or_null(SystemDictionary::java_platform_loader()); +} + +static ClassLoaderData* java_system_loader_data_or_null() { + return ClassLoaderData::class_loader_data_or_null(SystemDictionary::java_system_loader()); +} + +void ClassLoaderDataShared::iterate_symbols(MetaspaceClosure* closure) { + assert(DumpSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_boot_loader_data.iterate_symbols (null_class_loader_data(), closure); + _archived_platform_loader_data.iterate_symbols(java_platform_loader_data_or_null(), closure); + _archived_system_loader_data.iterate_symbols (java_system_loader_data_or_null(), closure); +} + +void ClassLoaderDataShared::allocate_archived_tables() { + assert(DumpSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_boot_loader_data.allocate (null_class_loader_data()); + _archived_platform_loader_data.allocate(java_platform_loader_data_or_null()); + _archived_system_loader_data.allocate (java_system_loader_data_or_null()); +} + +void ClassLoaderDataShared::init_archived_tables() { + assert(DumpSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_boot_loader_data.init_archived_entries (null_class_loader_data()); + _archived_platform_loader_data.init_archived_entries(java_platform_loader_data_or_null()); + _archived_system_loader_data.init_archived_entries (java_system_loader_data_or_null()); + _archived_javabase_moduleEntry = ModuleEntry::get_archived_entry(ModuleEntryTable::javabase_moduleEntry()); +} + +void ClassLoaderDataShared::init_archived_oops() { + assert(DumpSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_boot_loader_data.init_archived_oops (null_class_loader_data()); + _archived_platform_loader_data.init_archived_oops(java_platform_loader_data_or_null()); + _archived_system_loader_data.init_archived_oops (java_system_loader_data_or_null()); +} + +void ClassLoaderDataShared::serialize(SerializeClosure* f) { + _archived_boot_loader_data.serialize(f); + _archived_platform_loader_data.serialize(f); + _archived_system_loader_data.serialize(f); + f->do_ptr((void**)&_archived_javabase_moduleEntry); + + if (f->reading() && MetaspaceShared::use_full_module_graph()) { + // Must be done before ClassLoader::create_javabase() + _archived_boot_loader_data.restore(null_class_loader_data(), true, false); + ModuleEntryTable::set_javabase_moduleEntry(_archived_javabase_moduleEntry); + log_info(cds)("use_full_module_graph = true; java.base = " INTPTR_FORMAT, + p2i(_archived_javabase_moduleEntry)); + } +} + +oop ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data() { + assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_boot_loader_data.restore(null_class_loader_data(), false, true); + return _archived_javabase_moduleEntry->module(); +} + +void ClassLoaderDataShared::restore_java_platform_loader_from_archive(ClassLoaderData* loader_data) { + assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_platform_loader_data.restore(loader_data, true, true); +} + +void ClassLoaderDataShared::restore_java_system_loader_from_archive(ClassLoaderData* loader_data) { + assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_system_loader_data.restore(loader_data, true, true); +} + +#endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/classfile/classLoaderDataShared.hpp b/src/hotspot/share/classfile/classLoaderDataShared.hpp new file mode 100644 index 00000000000..03d8f51ae3b --- /dev/null +++ b/src/hotspot/share/classfile/classLoaderDataShared.hpp @@ -0,0 +1,47 @@ + /* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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_CLASSFILE_CLASSLOADERDATASHARED_HPP +#define SHARE_CLASSFILE_CLASSLOADERDATASHARED_HPP + +#include "memory/allStatic.hpp" +#include "oops/oopsHierarchy.hpp" + +class ClassLoaderData; +class MetaspaceClosure; +class SerializeClosure; + +class ClassLoaderDataShared : AllStatic { +public: + static void allocate_archived_tables(); + static void iterate_symbols(MetaspaceClosure* closure); + static void init_archived_tables(); + static void init_archived_oops(); + static void serialize(SerializeClosure* f); + static oop restore_archived_oops_for_null_class_loader_data(); + static void restore_java_platform_loader_from_archive(ClassLoaderData* loader_data); + static void restore_java_system_loader_from_archive(ClassLoaderData* loader_data); +}; + +#endif // SHARE_CLASSFILE_CLASSLOADERDATASHARED_HPP diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp index a5aa7563f2b..666b45404e0 100644 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ b/src/hotspot/share/classfile/classLoaderExt.cpp @@ -270,7 +270,7 @@ InstanceKlass* ClassLoaderExt::load_class(Symbol* name, const char* path, TRAPS) } { PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), - ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), + THREAD->as_Java_thread()->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_LOAD); stream = e->open_stream(file_name, CHECK_NULL); } diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 8b3afbc94c4..abaf2fb4f6e 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -408,8 +408,7 @@ Handle java_lang_String::create_from_platform_dependent_str(const char* str, TRA jstring js = NULL; { - assert(THREAD->is_Java_thread(), "must be java thread"); - JavaThread* thread = (JavaThread*)THREAD; + JavaThread* thread = THREAD->as_Java_thread(); HandleMark hm(thread); ThreadToNativeFromVM ttn(thread); js = (_to_java_string_fn)(thread->jni_environment(), str); @@ -435,8 +434,7 @@ char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) { } char *native_platform_string; - { JavaThread* thread = (JavaThread*)THREAD; - assert(thread->is_Java_thread(), "must be java thread"); + { JavaThread* thread = THREAD->as_Java_thread(); jstring js = (jstring) JNIHandles::make_local(thread, java_string()); bool is_copy; HandleMark hm(thread); @@ -2416,7 +2414,7 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHand clear_stacktrace(throwable()); int max_depth = MaxJavaStackTraceDepth; - JavaThread* thread = (JavaThread*)THREAD; + JavaThread* thread = THREAD->as_Java_thread(); BacktraceBuilder bt(CHECK); @@ -3394,12 +3392,17 @@ void java_lang_Module::set_name(oop module, oop value) { module->obj_field_put(_name_offset, value); } -ModuleEntry* java_lang_Module::module_entry(oop module) { +ModuleEntry* java_lang_Module::module_entry_raw(oop module) { assert(_module_entry_offset != 0, "Uninitialized module_entry_offset"); assert(module != NULL, "module can't be null"); assert(oopDesc::is_oop(module), "module must be oop"); ModuleEntry* module_entry = (ModuleEntry*)module->address_field(_module_entry_offset); + return module_entry; +} + +ModuleEntry* java_lang_Module::module_entry(oop module) { + ModuleEntry* module_entry = module_entry_raw(module); if (module_entry == NULL) { // If the inject field containing the ModuleEntry* is null then return the // class loader's unnamed module. @@ -4823,9 +4826,8 @@ bool JavaClasses::is_supported_for_archiving(oop obj) { Klass* klass = obj->klass(); if (klass == SystemDictionary::ClassLoader_klass() || // ClassLoader::loader_data is malloc'ed. - klass == SystemDictionary::Module_klass() || // Module::module_entry is malloc'ed // The next 3 classes are used to implement java.lang.invoke, and are not used directly in - // regular Java code. The implementation of java.lang.invoke uses generated anonymoys classes + // regular Java code. The implementation of java.lang.invoke uses generated anonymous classes // (e.g., as referenced by ResolvedMethodName::vmholder) that are not yet supported by CDS. // So for now we cannot not support these classes for archiving. // diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 537c2523bec..c7916cb4ea3 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -797,6 +797,7 @@ class java_lang_Module { static void set_name(oop module, oop value); static ModuleEntry* module_entry(oop module); + static ModuleEntry* module_entry_raw(oop module); static void set_module_entry(oop module, ModuleEntry* module_entry); friend class JavaClasses; diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp index d89018f1e7a..a02d01020b5 100644 --- a/src/hotspot/share/classfile/klassFactory.cpp +++ b/src/hotspot/share/classfile/klassFactory.cpp @@ -120,8 +120,7 @@ static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream, assert(stream != NULL, "invariant"); if (JvmtiExport::should_post_class_file_load_hook()) { - assert(THREAD->is_Java_thread(), "must be a JavaThread"); - const JavaThread* jt = (JavaThread*)THREAD; + const JavaThread* jt = THREAD->as_Java_thread(); Handle class_loader(THREAD, loader_data->class_loader()); diff --git a/src/hotspot/share/classfile/moduleEntry.cpp b/src/hotspot/share/classfile/moduleEntry.cpp index 80d96adb1d7..e1b45955b4f 100644 --- a/src/hotspot/share/classfile/moduleEntry.cpp +++ b/src/hotspot/share/classfile/moduleEntry.cpp @@ -29,7 +29,11 @@ #include "classfile/javaClasses.inline.hpp" #include "classfile/moduleEntry.hpp" #include "logging/log.hpp" +#include "memory/archiveBuilder.hpp" +#include "memory/archiveUtils.hpp" #include "memory/filemap.hpp" +#include "memory/heapShared.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/oopHandle.inline.hpp" @@ -40,6 +44,8 @@ #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/ostream.hpp" +#include "utilities/quickSort.hpp" +#include "utilities/resourceHash.hpp" ModuleEntry* ModuleEntryTable::_javabase_module = NULL; @@ -108,15 +114,15 @@ void ModuleEntry::set_version(Symbol* version) { // Returns the shared ProtectionDomain oop ModuleEntry::shared_protection_domain() { - return _pd.resolve(); + return _shared_pd.resolve(); } // Set the shared ProtectionDomain atomically void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd_h) { // Create a handle for the shared ProtectionDomain and save it atomically. - // init_handle_locked checks if someone beats us setting the _pd cache. - loader_data->init_handle_locked(_pd, pd_h); + // init_handle_locked checks if someone beats us setting the _shared_pd cache. + loader_data->init_handle_locked(_shared_pd, pd_h); } // Returns true if this module can read module m @@ -362,6 +368,203 @@ ModuleEntryTable::~ModuleEntryTable() { assert(new_entry_free_list() == NULL, "entry present on ModuleEntryTable's free list"); } +#if INCLUDE_CDS_JAVA_HEAP +typedef ResourceHashtable< + const ModuleEntry*, + ModuleEntry*, + primitive_hash<const ModuleEntry*>, + primitive_equals<const ModuleEntry*>, + 557, // prime number + ResourceObj::C_HEAP> ArchivedModuleEntries; +static ArchivedModuleEntries* _archive_modules_entries = NULL; + +ModuleEntry* ModuleEntry::allocate_archived_entry() const { + assert(is_named(), "unnamed packages/modules are not archived"); + ModuleEntry* archived_entry = (ModuleEntry*)MetaspaceShared::read_write_space_alloc(sizeof(ModuleEntry)); + memcpy((void*)archived_entry, (void*)this, sizeof(ModuleEntry)); + + if (_archive_modules_entries == NULL) { + _archive_modules_entries = new (ResourceObj::C_HEAP, mtClass)ArchivedModuleEntries(); + } + assert(_archive_modules_entries->get(this) == NULL, "Each ModuleEntry must not be shared across ModuleEntryTables"); + _archive_modules_entries->put(this, archived_entry); + + return archived_entry; +} + +ModuleEntry* ModuleEntry::get_archived_entry(ModuleEntry* orig_entry) { + ModuleEntry** ptr = _archive_modules_entries->get(orig_entry); + assert(ptr != NULL && *ptr != NULL, "must have been allocated"); + return *ptr; +} + +// This function is used to archive ModuleEntry::_reads and PackageEntry::_qualified_exports. +// GrowableArray cannot be directly archived, as it needs to be expandable at runtime. +// Write it out as an Array, and convert it back to GrowableArray at runtime. +Array<ModuleEntry*>* ModuleEntry::write_growable_array(GrowableArray<ModuleEntry*>* array) { + Array<ModuleEntry*>* archived_array = NULL; + int length = (array == NULL) ? 0 : array->length(); + if (length > 0) { + archived_array = MetaspaceShared::new_ro_array<ModuleEntry*>(length); + for (int i = 0; i < length; i++) { + ModuleEntry* archived_entry = get_archived_entry(array->at(i)); + archived_array->at_put(i, archived_entry); + ArchivePtrMarker::mark_pointer((address*)archived_array->adr_at(i)); + } + } + + return archived_array; +} + +GrowableArray<ModuleEntry*>* ModuleEntry::restore_growable_array(Array<ModuleEntry*>* archived_array) { + GrowableArray<ModuleEntry*>* array = NULL; + int length = (archived_array == NULL) ? 0 : archived_array->length(); + if (length > 0) { + array = new (ResourceObj::C_HEAP, mtModule)GrowableArray<ModuleEntry*>(length, mtModule); + for (int i = 0; i < length; i++) { + ModuleEntry* archived_entry = archived_array->at(i); + array->append(archived_entry); + } + } + + return array; +} + +void ModuleEntry::iterate_symbols(MetaspaceClosure* closure) { + closure->push(literal_addr()); // name + closure->push(&_version); + closure->push(&_location); +} + +void ModuleEntry::init_as_archived_entry() { + Array<ModuleEntry*>* archived_reads = write_growable_array(_reads); + + set_next(NULL); + set_hash(0x0); // re-init at runtime + _loader_data = NULL; // re-init at runtime + _shared_path_index = FileMapInfo::get_module_shared_path_index(_location); + if (literal() != NULL) { + set_literal(ArchiveBuilder::get_relocated_symbol(literal())); + ArchivePtrMarker::mark_pointer((address*)literal_addr()); + } + _reads = (GrowableArray<ModuleEntry*>*)archived_reads; + if (_version != NULL) { + _version = ArchiveBuilder::get_relocated_symbol(_version); + } + if (_location != NULL) { + _location = ArchiveBuilder::get_relocated_symbol(_location); + } + + ArchivePtrMarker::mark_pointer((address*)&_reads); + ArchivePtrMarker::mark_pointer((address*)&_version); + ArchivePtrMarker::mark_pointer((address*)&_location); +} + +void ModuleEntry::init_archived_oops() { + assert(DumpSharedSpaces, "static dump only"); + oop module_obj = module(); + if (module_obj != NULL) { + oop m = HeapShared::find_archived_heap_object(module_obj); + assert(m != NULL, "sanity"); + _archived_module_narrow_oop = CompressedOops::encode(m); + } + assert(shared_protection_domain() == NULL, "never set during -Xshare:dump"); + // Clear handles and restore at run time. Handles cannot be archived. + OopHandle null_handle; + _module = null_handle; +} + +void ModuleEntry::load_from_archive(ClassLoaderData* loader_data) { + set_loader_data(loader_data); + _reads = restore_growable_array((Array<ModuleEntry*>*)_reads); + JFR_ONLY(INIT_ID(this);) +} + +void ModuleEntry::restore_archive_oops(ClassLoaderData* loader_data) { + Handle module_handle(Thread::current(), HeapShared::materialize_archived_object(_archived_module_narrow_oop)); + assert(module_handle.not_null(), "huh"); + set_module(loader_data->add_handle(module_handle)); + + // This was cleared to zero during dump time -- we didn't save the value + // because it may be affected by archive relocation. + java_lang_Module::set_module_entry(module_handle(), this); + + if (loader_data->class_loader() != NULL) { + java_lang_Module::set_loader(module_handle(), loader_data->class_loader()); + } +} + +static int compare_module_by_name(ModuleEntry* a, ModuleEntry* b) { + assert(a == b || a->name() != b->name(), "no duplicated names"); + return a->name()->fast_compare(b->name()); +} + +void ModuleEntryTable::iterate_symbols(MetaspaceClosure* closure) { + for (int i = 0; i < table_size(); ++i) { + for (ModuleEntry* m = bucket(i); m != NULL; m = m->next()) { + m->iterate_symbols(closure); + } + } +} + +Array<ModuleEntry*>* ModuleEntryTable::allocate_archived_entries() { + Array<ModuleEntry*>* archived_modules = MetaspaceShared::new_rw_array<ModuleEntry*>(number_of_entries()); + int n = 0; + for (int i = 0; i < table_size(); ++i) { + for (ModuleEntry* m = bucket(i); m != NULL; m = m->next()) { + archived_modules->at_put(n++, m); + } + } + if (n > 1) { + // Always allocate in the same order to produce deterministic archive. + QuickSort::sort(archived_modules->data(), n, (_sort_Fn)compare_module_by_name, true); + } + for (int i = 0; i < n; i++) { + archived_modules->at_put(i, archived_modules->at(i)->allocate_archived_entry()); + ArchivePtrMarker::mark_pointer((address*)archived_modules->adr_at(i)); + } + return archived_modules; +} + +void ModuleEntryTable::init_archived_entries(Array<ModuleEntry*>* archived_modules) { + assert(DumpSharedSpaces, "dump time only"); + for (int i = 0; i < archived_modules->length(); i++) { + ModuleEntry* archived_entry = archived_modules->at(i); + archived_entry->init_as_archived_entry(); + } +} + +void ModuleEntryTable::init_archived_oops(Array<ModuleEntry*>* archived_modules) { + assert(DumpSharedSpaces, "dump time only"); + for (int i = 0; i < archived_modules->length(); i++) { + ModuleEntry* archived_entry = archived_modules->at(i); + archived_entry->init_archived_oops(); + } +} + +void ModuleEntryTable::load_archived_entries(ClassLoaderData* loader_data, + Array<ModuleEntry*>* archived_modules) { + assert(UseSharedSpaces, "runtime only"); + + for (int i = 0; i < archived_modules->length(); i++) { + ModuleEntry* archived_entry = archived_modules->at(i); + archived_entry->load_from_archive(loader_data); + + unsigned int hash = compute_hash(archived_entry->name()); + archived_entry->set_hash(hash); + add_entry(hash_to_index(hash), archived_entry); + } +} + +void ModuleEntryTable::restore_archived_oops(ClassLoaderData* loader_data, Array<ModuleEntry*>* archived_modules) { + assert(UseSharedSpaces, "runtime only"); + for (int i = 0; i < archived_modules->length(); i++) { + ModuleEntry* archived_entry = archived_modules->at(i); + archived_entry->restore_archive_oops(loader_data); + } +} +#endif // INCLUDE_CDS_JAVA_HEAP + ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle, bool is_open, Symbol* name, Symbol* version, Symbol* location, diff --git a/src/hotspot/share/classfile/moduleEntry.hpp b/src/hotspot/share/classfile/moduleEntry.hpp index 8aa885464c8..ec09fc3eda5 100644 --- a/src/hotspot/share/classfile/moduleEntry.hpp +++ b/src/hotspot/share/classfile/moduleEntry.hpp @@ -47,6 +47,8 @@ #define JAVA_BASE_NAME "java.base" #define JAVA_BASE_NAME_LEN 9 +template <class T> class Array; +class MetaspaceClosure; class ModuleClosure; // A ModuleEntry describes a module that has been defined by a call to JVM_DefineModule. @@ -63,7 +65,7 @@ class ModuleClosure; class ModuleEntry : public HashtableEntry<Symbol*, mtModule> { private: OopHandle _module; // java.lang.Module - OopHandle _pd; // java.security.ProtectionDomain, cached + OopHandle _shared_pd; // java.security.ProtectionDomain, cached // for shared classes from this module ClassLoaderData* _loader_data; GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module @@ -75,13 +77,15 @@ class ModuleEntry : public HashtableEntry<Symbol*, mtModule> { bool _must_walk_reads; // walk module's reads list at GC safepoints to purge out dead modules bool _is_open; // whether the packages in the module are all unqualifiedly exported bool _is_patched; // whether the module is patched via --patch-module + CDS_JAVA_HEAP_ONLY(narrowOop _archived_module_narrow_oop;) + JFR_ONLY(DEFINE_TRACE_ID_FIELD;) enum {MODULE_READS_SIZE = 101}; // Initial size of list of modules that the module can read. public: void init() { _module = OopHandle(); - _pd = OopHandle(); + _shared_pd = OopHandle(); _loader_data = NULL; _reads = NULL; _version = NULL; @@ -188,6 +192,18 @@ class ModuleEntry : public HashtableEntry<Symbol*, mtModule> { CDS_ONLY(int shared_path_index() { return _shared_path_index;}) JFR_ONLY(DEFINE_TRACE_ID_METHODS;) + +#if INCLUDE_CDS_JAVA_HEAP + void iterate_symbols(MetaspaceClosure* closure); + ModuleEntry* allocate_archived_entry() const; + void init_as_archived_entry(); + void init_archived_oops(); + static ModuleEntry* get_archived_entry(ModuleEntry* orig_entry); + static Array<ModuleEntry*>* write_growable_array(GrowableArray<ModuleEntry*>* array); + static GrowableArray<ModuleEntry*>* restore_growable_array(Array<ModuleEntry*>* archived_array); + void load_from_archive(ClassLoaderData* loader_data); + void restore_archive_oops(ClassLoaderData* loader_data); +#endif }; // Iterator interface @@ -270,6 +286,17 @@ class ModuleEntryTable : public Hashtable<Symbol*, mtModule> { void print(outputStream* st = tty); void verify(); + +#if INCLUDE_CDS_JAVA_HEAP + void iterate_symbols(MetaspaceClosure* closure); + Array<ModuleEntry*>* allocate_archived_entries(); + void init_archived_entries(Array<ModuleEntry*>* archived_modules); + void init_archived_oops(Array<ModuleEntry*>* archived_modules); + void load_archived_entries(ClassLoaderData* loader_data, + Array<ModuleEntry*>* archived_modules); + void restore_archived_oops(ClassLoaderData* loader_data, + Array<ModuleEntry*>* archived_modules); +#endif }; #endif // SHARE_CLASSFILE_MODULEENTRY_HPP diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp index 1b09052e601..b0dd93d0c21 100644 --- a/src/hotspot/share/classfile/modules.cpp +++ b/src/hotspot/share/classfile/modules.cpp @@ -27,6 +27,7 @@ #include "classfile/classFileParser.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderDataShared.hpp" #include "classfile/javaAssertions.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaClasses.inline.hpp" @@ -39,7 +40,9 @@ #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvmtiExport.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" @@ -268,6 +271,7 @@ void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRA void Modules::define_module(jobject module, jboolean is_open, jstring version, jstring location, jobjectArray packages, TRAPS) { + check_cds_restrictions(CHECK); ResourceMark rm(THREAD); if (module == NULL) { @@ -450,6 +454,46 @@ void Modules::define_module(jobject module, jboolean is_open, jstring version, } } +#if INCLUDE_CDS_JAVA_HEAP +void Modules::define_archived_modules(jobject platform_loader, jobject system_loader, TRAPS) { + assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + + // We don't want the classes used by the archived full module graph to be redefined by JVMTI. + // Luckily, such classes are loaded in the JVMTI "early" phase, and CDS is disabled if a JVMTI + // agent wants to redefine classes in this phase. + JVMTI_ONLY(assert(JvmtiExport::is_early_phase(), "must be")); + assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()), + "CDS should be disabled if early class hooks are enabled"); + + Handle java_base_module(THREAD, ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data()); + // Patch any previously loaded class's module field with java.base's java.lang.Module. + ModuleEntryTable::patch_javabase_entries(java_base_module); + + if (platform_loader == NULL) { + THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null platform loader object"); + } + + if (system_loader == NULL) { + THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null system loader object"); + } + + Handle h_platform_loader(THREAD, JNIHandles::resolve_non_null(platform_loader)); + ClassLoaderData* platform_loader_data = SystemDictionary::register_loader(h_platform_loader); + ClassLoaderDataShared::restore_java_platform_loader_from_archive(platform_loader_data); + + Handle h_system_loader(THREAD, JNIHandles::resolve_non_null(system_loader)); + ClassLoaderData* system_loader_data = SystemDictionary::register_loader(h_system_loader); + ClassLoaderDataShared::restore_java_system_loader_from_archive(system_loader_data); +} + +void Modules::check_cds_restrictions(TRAPS) { + if (DumpSharedSpaces && Universe::is_module_initialized() && MetaspaceShared::use_full_module_graph()) { + THROW_MSG(vmSymbols::java_lang_UnsupportedOperationException(), + "During -Xshare:dump, module system cannot be modified after it's initialized"); + } +} +#endif // INCLUDE_CDS_JAVA_HEAP + void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) { ResourceMark rm(THREAD); @@ -488,6 +532,7 @@ void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) { } void Modules::add_module_exports(jobject from_module, jstring package_name, jobject to_module, TRAPS) { + check_cds_restrictions(CHECK); if (package_name == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), @@ -555,6 +600,7 @@ void Modules::add_module_exports(jobject from_module, jstring package_name, jobj void Modules::add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS) { + check_cds_restrictions(CHECK); if (to_module == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), "to_module is null"); @@ -563,6 +609,7 @@ void Modules::add_module_exports_qualified(jobject from_module, jstring package, } void Modules::add_reads_module(jobject from_module, jobject to_module, TRAPS) { + check_cds_restrictions(CHECK); if (from_module == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), "from_module is null"); @@ -668,6 +715,7 @@ jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRA // Export package in module to all unnamed modules. void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package_name, TRAPS) { + check_cds_restrictions(CHECK); if (module == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), "module is null"); diff --git a/src/hotspot/share/classfile/modules.hpp b/src/hotspot/share/classfile/modules.hpp index 434a0cfaf23..b76aa8b4aed 100644 --- a/src/hotspot/share/classfile/modules.hpp +++ b/src/hotspot/share/classfile/modules.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * 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 @@ class ModuleEntryTable; class Symbol; class Modules : AllStatic { + static void check_cds_restrictions(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; public: // define_module defines a module containing the specified packages. It binds the @@ -52,6 +53,9 @@ class Modules : AllStatic { static void define_module(jobject module, jboolean is_open, jstring version, jstring location, jobjectArray packages, TRAPS); + static void define_archived_modules(jobject platform_loader, jobject system_loader, + TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + // Provides the java.lang.Module for the unnamed module defined // to the boot loader. // diff --git a/src/hotspot/share/classfile/packageEntry.cpp b/src/hotspot/share/classfile/packageEntry.cpp index 48475f33183..da83bd519aa 100644 --- a/src/hotspot/share/classfile/packageEntry.cpp +++ b/src/hotspot/share/classfile/packageEntry.cpp @@ -26,7 +26,11 @@ #include "classfile/moduleEntry.hpp" #include "classfile/packageEntry.hpp" #include "logging/log.hpp" +#include "memory/archiveBuilder.hpp" +#include "memory/archiveUtils.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" +#include "oops/array.hpp" #include "oops/symbol.hpp" #include "runtime/java.hpp" #include "runtime/handles.inline.hpp" @@ -34,6 +38,8 @@ #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/ostream.hpp" +#include "utilities/quickSort.hpp" +#include "utilities/resourceHash.hpp" // Returns true if this package specifies m as a qualified export, including through an unnamed export bool PackageEntry::is_qexported_to(ModuleEntry* m) const { @@ -189,6 +195,126 @@ PackageEntryTable::~PackageEntryTable() { assert(new_entry_free_list() == NULL, "entry present on PackageEntryTable's free list"); } +#if INCLUDE_CDS_JAVA_HEAP +typedef ResourceHashtable< + const PackageEntry*, + PackageEntry*, + primitive_hash<const PackageEntry*>, + primitive_equals<const PackageEntry*>, + 557, // prime number + ResourceObj::C_HEAP> ArchivedPackageEntries; +static ArchivedPackageEntries* _archived_packages_entries = NULL; + +PackageEntry* PackageEntry::allocate_archived_entry() const { + assert(!in_unnamed_module(), "unnamed packages/modules are not archived"); + PackageEntry* archived_entry = (PackageEntry*)MetaspaceShared::read_write_space_alloc(sizeof(PackageEntry)); + memcpy((void*)archived_entry, (void*)this, sizeof(PackageEntry)); + + if (_archived_packages_entries == NULL) { + _archived_packages_entries = new (ResourceObj::C_HEAP, mtClass)ArchivedPackageEntries(); + } + assert(_archived_packages_entries->get(this) == NULL, "Each PackageEntry must not be shared across PackageEntryTables"); + _archived_packages_entries->put(this, archived_entry); + + return archived_entry; +} + +PackageEntry* PackageEntry::get_archived_entry(PackageEntry* orig_entry) { + PackageEntry** ptr = _archived_packages_entries->get(orig_entry); + assert(ptr != NULL && *ptr != NULL, "must have been allocated"); + return *ptr; +} + +void PackageEntry::iterate_symbols(MetaspaceClosure* closure) { + closure->push(literal_addr()); // name +} + +void PackageEntry::init_as_archived_entry() { + Array<ModuleEntry*>* archived_qualified_exports = ModuleEntry::write_growable_array(_qualified_exports); + + set_next(NULL); + set_literal(ArchiveBuilder::get_relocated_symbol(literal())); + set_hash(0x0); // re-init at runtime + _module = ModuleEntry::get_archived_entry(_module); + _qualified_exports = (GrowableArray<ModuleEntry*>*)archived_qualified_exports; + _defined_by_cds_in_class_path = 0; + + ArchivePtrMarker::mark_pointer((address*)literal_addr()); + ArchivePtrMarker::mark_pointer((address*)&_module); + ArchivePtrMarker::mark_pointer((address*)&_qualified_exports); +} + +void PackageEntry::load_from_archive() { + _qualified_exports = ModuleEntry::restore_growable_array((Array<ModuleEntry*>*)_qualified_exports); + JFR_ONLY(INIT_ID(this);) +} + +static int compare_package_by_name(PackageEntry* a, PackageEntry* b) { + assert(a == b || a->name() != b->name(), "no duplicated names"); + return a->name()->fast_compare(b->name()); +} + +void PackageEntryTable::iterate_symbols(MetaspaceClosure* closure) { + for (int i = 0; i < table_size(); ++i) { + for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) { + p->iterate_symbols(closure); + } + } +} + +Array<PackageEntry*>* PackageEntryTable::allocate_archived_entries() { + // First count the packages in named modules + int n, i; + for (n = 0, i = 0; i < table_size(); ++i) { + for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) { + if (p->module()->name() != NULL) { + n++; + } + } + } + + Array<PackageEntry*>* archived_packages = MetaspaceShared::new_rw_array<PackageEntry*>(n); + for (n = 0, i = 0; i < table_size(); ++i) { + for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) { + if (p->module()->name() != NULL) { + // We don't archive unnamed modules, or packages in unnamed modules. They will be + // created on-demand at runtime as classes in such packages are loaded. + archived_packages->at_put(n++, p); + } + } + } + if (n > 1) { + QuickSort::sort(archived_packages->data(), n, (_sort_Fn)compare_package_by_name, true); + } + for (i = 0; i < n; i++) { + archived_packages->at_put(i, archived_packages->at(i)->allocate_archived_entry()); + ArchivePtrMarker::mark_pointer((address*)archived_packages->adr_at(i)); + } + return archived_packages; +} + +void PackageEntryTable::init_archived_entries(Array<PackageEntry*>* archived_packages) { + for (int i = 0; i < archived_packages->length(); i++) { + PackageEntry* archived_entry = archived_packages->at(i); + archived_entry->init_as_archived_entry(); + } +} + +void PackageEntryTable::load_archived_entries(Array<PackageEntry*>* archived_packages) { + assert(UseSharedSpaces, "runtime only"); + + for (int i = 0; i < archived_packages->length(); i++) { + PackageEntry* archived_entry = archived_packages->at(i); + archived_entry->load_from_archive(); + + unsigned int hash = compute_hash(archived_entry->name()); + archived_entry->set_hash(hash); + add_entry(hash_to_index(hash), archived_entry); + } +} + +#endif // INCLUDE_CDS_JAVA_HEAP + PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) { assert(Module_lock->owned_by_self(), "should have the Module_lock"); PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name); @@ -274,7 +400,6 @@ void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_lis } } } - } // iteration of qualified exports diff --git a/src/hotspot/share/classfile/packageEntry.hpp b/src/hotspot/share/classfile/packageEntry.hpp index ee2bfe86a6f..5bfd565dc3e 100644 --- a/src/hotspot/share/classfile/packageEntry.hpp +++ b/src/hotspot/share/classfile/packageEntry.hpp @@ -36,6 +36,8 @@ #include "jfr/support/jfrTraceIdExtension.hpp" #endif +template <class T> class Array; +class MetaspaceClosure; // A PackageEntry basically represents a Java package. It contains: // - Symbol* containing the package's name. @@ -217,6 +219,14 @@ class PackageEntry : public HashtableEntry<Symbol*, mtModule> { void print(outputStream* st = tty); void verify(); +#if INCLUDE_CDS_JAVA_HEAP + void iterate_symbols(MetaspaceClosure* closure); + PackageEntry* allocate_archived_entry() const; + void init_as_archived_entry(); + static PackageEntry* get_archived_entry(PackageEntry* orig_entry); + void load_from_archive(); +#endif + static int max_index_for_defined_in_class_path() { return sizeof(int) * BitsPerByte; } @@ -295,6 +305,13 @@ class PackageEntryTable : public Hashtable<Symbol*, mtModule> { void print(outputStream* st = tty); void verify(); + +#if INCLUDE_CDS_JAVA_HEAP + void iterate_symbols(MetaspaceClosure* closure); + Array<PackageEntry*>* allocate_archived_entries(); + void init_archived_entries(Array<PackageEntry*>* archived_packages); + void load_archived_entries(Array<PackageEntry*>* archived_packages); +#endif }; #endif // SHARE_CLASSFILE_PACKAGEENTRY_HPP diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 8742557ffbe..606a84345ef 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -565,7 +565,7 @@ void SystemDictionary::double_lock_wait(Handle lockObject, TRAPS) { assert_lock_strong(SystemDictionary_lock); bool calledholdinglock - = ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, lockObject); + = ObjectSynchronizer::current_thread_holds_lock(THREAD->as_Java_thread(), lockObject); assert(calledholdinglock,"must hold lock for notify"); assert((lockObject() != _system_loader_lock_obj.resolve() && !is_parallelCapable(lockObject)), "unexpected double_lock_wait"); @@ -898,9 +898,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, } if (JvmtiExport::should_post_class_load()) { - Thread *thread = THREAD; - assert(thread->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) thread, k); + JvmtiExport::post_class_load(THREAD->as_Java_thread(), k); } } } @@ -1084,8 +1082,7 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, // notify jvmti if (JvmtiExport::should_post_class_load()) { - assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) THREAD, k); + JvmtiExport::post_class_load(THREAD->as_Java_thread(), k); } if (class_load_start_event.should_commit()) { post_class_load_event(&class_load_start_event, k, loader_data); @@ -1583,8 +1580,7 @@ InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle // Use user specified class loader to load class. Call loadClass operation on class_loader. ResourceMark rm(THREAD); - assert(THREAD->is_Java_thread(), "must be a JavaThread"); - JavaThread* jt = (JavaThread*) THREAD; + JavaThread* jt = THREAD->as_Java_thread(); PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time(), ClassLoader::perf_app_classload_selftime(), @@ -1647,15 +1643,15 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { ClassLoaderData* loader_data = k->class_loader_data(); Handle class_loader_h(THREAD, loader_data->class_loader()); - // for bootstrap and other parallel classloaders don't acquire lock, - // use placeholder token - // If a parallelCapable class loader calls define_instance_class instead of - // find_or_define_instance_class to get here, we have a timing - // hole with systemDictionary updates and check_constraints - if (!class_loader_h.is_null() && !is_parallelCapable(class_loader_h)) { - assert(ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, - compute_loader_lock_object(class_loader_h, THREAD)), - "define called without lock"); + // for bootstrap and other parallel classloaders don't acquire lock, + // use placeholder token + // If a parallelCapable class loader calls define_instance_class instead of + // find_or_define_instance_class to get here, we have a timing + // hole with systemDictionary updates and check_constraints + if (!class_loader_h.is_null() && !is_parallelCapable(class_loader_h)) { + assert(ObjectSynchronizer::current_thread_holds_lock(THREAD->as_Java_thread(), + compute_loader_lock_object(class_loader_h, THREAD)), + "define called without lock"); } // Check class-loading constraints. Throw exception if violation is detected. @@ -1705,9 +1701,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { // notify jvmti if (JvmtiExport::should_post_class_load()) { - assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) THREAD, k); - + JvmtiExport::post_class_load(THREAD->as_Java_thread(), k); } post_class_define_event(k, loader_data); } @@ -1832,7 +1826,7 @@ void SystemDictionary::check_loader_lock_contention(Handle loader_lock, TRAPS) { assert(!loader_lock.is_null(), "NULL lock object"); - if (ObjectSynchronizer::query_lock_ownership((JavaThread*)THREAD, loader_lock) + if (ObjectSynchronizer::query_lock_ownership(THREAD->as_Java_thread(), loader_lock) == ObjectSynchronizer::owner_other) { // contention will likely happen, so increment the corresponding // contention counter. diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 743ed212ca9..1b481c10385 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -187,10 +187,13 @@ class TableStatistics; do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream ) \ do_klass(URL_klass, java_net_URL ) \ do_klass(Jar_Manifest_klass, java_util_jar_Manifest ) \ + do_klass(jdk_internal_loader_BuiltinClassLoader_klass,jdk_internal_loader_BuiltinClassLoader ) \ do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders ) \ do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader) \ do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader) \ do_klass(CodeSource_klass, java_security_CodeSource ) \ + do_klass(ConcurrentHashMap_klass, java_util_concurrent_ConcurrentHashMap ) \ + do_klass(ArrayList_klass, java_util_ArrayList ) \ \ do_klass(StackTraceElement_klass, java_lang_StackTraceElement ) \ \ diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index a55d3112241..304afaba3b3 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -655,6 +655,22 @@ static RunTimeSharedDictionary _unregistered_dictionary; static RunTimeSharedDictionary _dynamic_builtin_dictionary; static RunTimeSharedDictionary _dynamic_unregistered_dictionary; + +Handle SystemDictionaryShared::create_jar_manifest(const char* manifest_chars, size_t size, TRAPS) { + typeArrayOop buf = oopFactory::new_byteArray((int)size, CHECK_NH); + typeArrayHandle bufhandle(THREAD, buf); + ArrayAccess<>::arraycopy_from_native(reinterpret_cast<const jbyte*>(manifest_chars), + buf, typeArrayOopDesc::element_offset<jbyte>(0), size); + Handle bais = JavaCalls::construct_new_instance(SystemDictionary::ByteArrayInputStream_klass(), + vmSymbols::byte_array_void_signature(), + bufhandle, CHECK_NH); + // manifest = new Manifest(ByteArrayInputStream) + Handle manifest = JavaCalls::construct_new_instance(SystemDictionary::Jar_Manifest_klass(), + vmSymbols::input_stream_void_signature(), + bais, CHECK_NH); + return manifest; +} + oop SystemDictionaryShared::shared_protection_domain(int index) { return ((objArrayOop)_shared_protection_domains.resolve())->obj_at(index); } @@ -671,30 +687,17 @@ Handle SystemDictionaryShared::get_shared_jar_manifest(int shared_path_index, TR Handle manifest ; if (shared_jar_manifest(shared_path_index) == NULL) { SharedClassPathEntry* ent = FileMapInfo::shared_path(shared_path_index); - long size = ent->manifest_size(); - if (size <= 0) { + size_t size = (size_t)ent->manifest_size(); + if (size == 0) { return Handle(); } // ByteArrayInputStream bais = new ByteArrayInputStream(buf); const char* src = ent->manifest(); assert(src != NULL, "No Manifest data"); - typeArrayOop buf = oopFactory::new_byteArray(size, CHECK_NH); - typeArrayHandle bufhandle(THREAD, buf); - ArrayAccess<>::arraycopy_from_native(reinterpret_cast<const jbyte*>(src), - buf, typeArrayOopDesc::element_offset<jbyte>(0), size); - - Handle bais = JavaCalls::construct_new_instance(SystemDictionary::ByteArrayInputStream_klass(), - vmSymbols::byte_array_void_signature(), - bufhandle, CHECK_NH); - - // manifest = new Manifest(bais) - manifest = JavaCalls::construct_new_instance(SystemDictionary::Jar_Manifest_klass(), - vmSymbols::input_stream_void_signature(), - bais, CHECK_NH); + manifest = create_jar_manifest(src, size, THREAD); 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; @@ -1616,8 +1619,7 @@ InstanceKlass* SystemDictionaryShared::prepare_shared_lambda_proxy_class(Instanc loaded_lambda->link_class(CHECK_NULL); // notify jvmti if (JvmtiExport::should_post_class_load()) { - assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) THREAD, loaded_lambda); + JvmtiExport::post_class_load(THREAD->as_Java_thread(), loaded_lambda); } if (class_load_start_event.should_commit()) { SystemDictionary::post_class_load_event(&class_load_start_event, loaded_lambda, ClassLoaderData::class_loader_data(class_loader())); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index e7b6974a007..fe55b7a5cd7 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -320,6 +320,7 @@ class SystemDictionaryShared: public SystemDictionary { static void print_table_statistics(outputStream* st) NOT_CDS_RETURN; static bool empty_dumptime_table() NOT_CDS_RETURN_(true); static void start_dumping() NOT_CDS_RETURN; + static Handle create_jar_manifest(const char* man, size_t size, TRAPS) NOT_CDS_RETURN_(Handle()); DEBUG_ONLY(static bool no_class_loading_should_happen() {return _no_class_loading_should_happen;}) diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 9edd1daa056..25511485a6c 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -173,7 +173,7 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) { // Timer includes any side effects of class verification (resolution, // etc), but not recursive calls to Verifier::verify(). - JavaThread* jt = (JavaThread*)THREAD; + JavaThread* jt = THREAD->as_Java_thread(); PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(), ClassLoader::perf_class_verify_selftime(), ClassLoader::perf_classes_verified(), @@ -296,7 +296,7 @@ bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_ve Symbol* Verifier::inference_verify( InstanceKlass* klass, char* message, size_t message_len, TRAPS) { - JavaThread* thread = (JavaThread*)THREAD; + JavaThread* thread = THREAD->as_Java_thread(); verify_byte_codes_fn_t verify_func = verify_byte_codes_fn(); diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp new file mode 100644 index 00000000000..70932aede66 --- /dev/null +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -0,0 +1,852 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "classfile/vmIntrinsics.hpp" +#include "classfile/vmSymbols.hpp" +#include "compiler/compilerDirectives.hpp" +#include "utilities/xmlstream.hpp" + +// These are flag-matching functions: +inline bool match_F_R(jshort flags) { + const int req = 0; + const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; + return (flags & (req | neg)) == req; +} + +inline bool match_F_Y(jshort flags) { + const int req = JVM_ACC_SYNCHRONIZED; + const int neg = JVM_ACC_STATIC; + return (flags & (req | neg)) == req; +} + +inline bool match_F_RN(jshort flags) { + const int req = JVM_ACC_NATIVE; + const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; + return (flags & (req | neg)) == req; +} + +inline bool match_F_S(jshort flags) { + const int req = JVM_ACC_STATIC; + const int neg = JVM_ACC_SYNCHRONIZED; + return (flags & (req | neg)) == req; +} + +inline bool match_F_SN(jshort flags) { + const int req = JVM_ACC_STATIC | JVM_ACC_NATIVE; + const int neg = JVM_ACC_SYNCHRONIZED; + return (flags & (req | neg)) == req; +} + +inline bool match_F_RNY(jshort flags) { + const int req = JVM_ACC_NATIVE | JVM_ACC_SYNCHRONIZED; + const int neg = JVM_ACC_STATIC; + return (flags & (req | neg)) == req; +} + +static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) { +#define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0)) + switch (TYPE2(type, unboxing)) { +#define BASIC_TYPE_CASE(type, box, unbox) \ + case TYPE2(type, false): return vmIntrinsics::box; \ + case TYPE2(type, true): return vmIntrinsics::unbox + BASIC_TYPE_CASE(T_BOOLEAN, _Boolean_valueOf, _booleanValue); + BASIC_TYPE_CASE(T_BYTE, _Byte_valueOf, _byteValue); + BASIC_TYPE_CASE(T_CHAR, _Character_valueOf, _charValue); + BASIC_TYPE_CASE(T_SHORT, _Short_valueOf, _shortValue); + BASIC_TYPE_CASE(T_INT, _Integer_valueOf, _intValue); + BASIC_TYPE_CASE(T_LONG, _Long_valueOf, _longValue); + BASIC_TYPE_CASE(T_FLOAT, _Float_valueOf, _floatValue); + BASIC_TYPE_CASE(T_DOUBLE, _Double_valueOf, _doubleValue); +#undef BASIC_TYPE_CASE + } +#undef TYPE2 + return vmIntrinsics::_none; +} + +vmIntrinsics::ID vmIntrinsics::for_boxing(BasicType type) { + return wrapper_intrinsic(type, false); +} +vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) { + return wrapper_intrinsic(type, true); +} + +vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) { +#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d)) + switch (SRC_DEST(src, dest)) { + case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat; + case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits; + + case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble; + case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits; + } +#undef SRC_DEST + + return vmIntrinsics::_none; +} + +bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + switch(id) { +#ifdef JFR_HAVE_INTRINSICS + case vmIntrinsics::_counterTime: +#endif + case vmIntrinsics::_currentTimeMillis: + case vmIntrinsics::_nanoTime: + case vmIntrinsics::_floatToRawIntBits: + case vmIntrinsics::_intBitsToFloat: + case vmIntrinsics::_doubleToRawLongBits: + case vmIntrinsics::_longBitsToDouble: + case vmIntrinsics::_getClass: + case vmIntrinsics::_isInstance: + case vmIntrinsics::_currentThread: + case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: + case vmIntrinsics::_dsqrt: + case vmIntrinsics::_dsin: + case vmIntrinsics::_dcos: + case vmIntrinsics::_dtan: + case vmIntrinsics::_dlog: + case vmIntrinsics::_dlog10: + case vmIntrinsics::_dexp: + case vmIntrinsics::_dpow: + case vmIntrinsics::_checkIndex: + case vmIntrinsics::_Reference_get: + case vmIntrinsics::_updateCRC32: + case vmIntrinsics::_updateBytesCRC32: + case vmIntrinsics::_updateByteBufferCRC32: + case vmIntrinsics::_vectorizedMismatch: + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: + return true; + default: + return false; + } +} + +bool vmIntrinsics::can_trap(vmIntrinsics::ID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + switch(id) { +#ifdef JFR_HAVE_INTRINSICS + case vmIntrinsics::_counterTime: + case vmIntrinsics::_getClassId: +#endif + case vmIntrinsics::_currentTimeMillis: + case vmIntrinsics::_nanoTime: + case vmIntrinsics::_floatToRawIntBits: + case vmIntrinsics::_intBitsToFloat: + case vmIntrinsics::_doubleToRawLongBits: + case vmIntrinsics::_longBitsToDouble: + case vmIntrinsics::_currentThread: + case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: + case vmIntrinsics::_dsqrt: + case vmIntrinsics::_dsin: + case vmIntrinsics::_dcos: + case vmIntrinsics::_dtan: + case vmIntrinsics::_dlog: + case vmIntrinsics::_dlog10: + case vmIntrinsics::_dexp: + case vmIntrinsics::_dpow: + case vmIntrinsics::_updateCRC32: + case vmIntrinsics::_updateBytesCRC32: + case vmIntrinsics::_updateByteBufferCRC32: + case vmIntrinsics::_vectorizedMismatch: + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: + return false; + default: + return true; + } +} + +// Some intrinsics produce different results if they are not pinned +bool vmIntrinsics::should_be_pinned(vmIntrinsics::ID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + switch(id) { +#ifdef JFR_HAVE_INTRINSICS + case vmIntrinsics::_counterTime: +#endif + case vmIntrinsics::_currentTimeMillis: + case vmIntrinsics::_nanoTime: + return true; + default: + return false; + } +} + +bool vmIntrinsics::does_virtual_dispatch(vmIntrinsics::ID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + switch(id) { + case vmIntrinsics::_hashCode: + case vmIntrinsics::_clone: + return true; + break; + default: + return false; + } +} + +int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + switch (id) { + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: + case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: + case vmIntrinsics::_electronicCodeBook_encryptAESCrypt: + case vmIntrinsics::_electronicCodeBook_decryptAESCrypt: + case vmIntrinsics::_counterMode_AESCrypt: + return 1; + case vmIntrinsics::_digestBase_implCompressMB: + return 4; + default: + return 0; + } +} + +bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + + // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in + // the following switch statement. + if (!InlineNatives) { + switch (id) { + case vmIntrinsics::_indexOfL: + case vmIntrinsics::_indexOfU: + case vmIntrinsics::_indexOfUL: + case vmIntrinsics::_indexOfIL: + case vmIntrinsics::_indexOfIU: + case vmIntrinsics::_indexOfIUL: + case vmIntrinsics::_indexOfU_char: + case vmIntrinsics::_compareToL: + case vmIntrinsics::_compareToU: + case vmIntrinsics::_compareToLU: + case vmIntrinsics::_compareToUL: + case vmIntrinsics::_equalsL: + case vmIntrinsics::_equalsU: + case vmIntrinsics::_equalsC: + case vmIntrinsics::_getCharStringU: + case vmIntrinsics::_putCharStringU: + case vmIntrinsics::_compressStringC: + case vmIntrinsics::_compressStringB: + case vmIntrinsics::_inflateStringC: + case vmIntrinsics::_inflateStringB: + case vmIntrinsics::_getAndAddInt: + case vmIntrinsics::_getAndAddLong: + case vmIntrinsics::_getAndSetInt: + case vmIntrinsics::_getAndSetLong: + case vmIntrinsics::_getAndSetReference: + case vmIntrinsics::_loadFence: + case vmIntrinsics::_storeFence: + case vmIntrinsics::_fullFence: + case vmIntrinsics::_hasNegatives: + case vmIntrinsics::_Reference_get: + break; + default: + return true; + } + } + + switch (id) { + case vmIntrinsics::_isInstance: + case vmIntrinsics::_isAssignableFrom: + case vmIntrinsics::_getModifiers: + case vmIntrinsics::_isInterface: + case vmIntrinsics::_isArray: + case vmIntrinsics::_isPrimitive: + case vmIntrinsics::_isHidden: + case vmIntrinsics::_getSuperclass: + case vmIntrinsics::_Class_cast: + case vmIntrinsics::_getLength: + case vmIntrinsics::_newArray: + case vmIntrinsics::_getClass: + if (!InlineClassNatives) return true; + break; + case vmIntrinsics::_currentThread: + if (!InlineThreadNatives) return true; + break; + case vmIntrinsics::_floatToRawIntBits: + case vmIntrinsics::_intBitsToFloat: + case vmIntrinsics::_doubleToRawLongBits: + case vmIntrinsics::_longBitsToDouble: + case vmIntrinsics::_ceil: + case vmIntrinsics::_floor: + case vmIntrinsics::_rint: + case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: + case vmIntrinsics::_dsqrt: + case vmIntrinsics::_dsin: + case vmIntrinsics::_dcos: + case vmIntrinsics::_dtan: + case vmIntrinsics::_dlog: + case vmIntrinsics::_dexp: + case vmIntrinsics::_dpow: + case vmIntrinsics::_dlog10: + case vmIntrinsics::_datan2: + case vmIntrinsics::_min: + case vmIntrinsics::_max: + case vmIntrinsics::_floatToIntBits: + case vmIntrinsics::_doubleToLongBits: + case vmIntrinsics::_maxF: + case vmIntrinsics::_minF: + case vmIntrinsics::_maxD: + case vmIntrinsics::_minD: + if (!InlineMathNatives) return true; + break; + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: + if (!InlineMathNatives || !UseFMA) return true; + break; + case vmIntrinsics::_arraycopy: + if (!InlineArrayCopy) return true; + break; + case vmIntrinsics::_updateCRC32: + case vmIntrinsics::_updateBytesCRC32: + case vmIntrinsics::_updateByteBufferCRC32: + if (!UseCRC32Intrinsics) return true; + break; + case vmIntrinsics::_getReference: + case vmIntrinsics::_getBoolean: + case vmIntrinsics::_getByte: + case vmIntrinsics::_getShort: + case vmIntrinsics::_getChar: + case vmIntrinsics::_getInt: + case vmIntrinsics::_getLong: + case vmIntrinsics::_getFloat: + case vmIntrinsics::_getDouble: + case vmIntrinsics::_putReference: + case vmIntrinsics::_putBoolean: + case vmIntrinsics::_putByte: + case vmIntrinsics::_putShort: + case vmIntrinsics::_putChar: + case vmIntrinsics::_putInt: + case vmIntrinsics::_putLong: + case vmIntrinsics::_putFloat: + case vmIntrinsics::_putDouble: + case vmIntrinsics::_getReferenceVolatile: + case vmIntrinsics::_getBooleanVolatile: + case vmIntrinsics::_getByteVolatile: + case vmIntrinsics::_getShortVolatile: + case vmIntrinsics::_getCharVolatile: + case vmIntrinsics::_getIntVolatile: + case vmIntrinsics::_getLongVolatile: + case vmIntrinsics::_getFloatVolatile: + case vmIntrinsics::_getDoubleVolatile: + case vmIntrinsics::_putReferenceVolatile: + case vmIntrinsics::_putBooleanVolatile: + case vmIntrinsics::_putByteVolatile: + case vmIntrinsics::_putShortVolatile: + case vmIntrinsics::_putCharVolatile: + case vmIntrinsics::_putIntVolatile: + case vmIntrinsics::_putLongVolatile: + case vmIntrinsics::_putFloatVolatile: + case vmIntrinsics::_putDoubleVolatile: + case vmIntrinsics::_getReferenceAcquire: + case vmIntrinsics::_getBooleanAcquire: + case vmIntrinsics::_getByteAcquire: + case vmIntrinsics::_getShortAcquire: + case vmIntrinsics::_getCharAcquire: + case vmIntrinsics::_getIntAcquire: + case vmIntrinsics::_getLongAcquire: + case vmIntrinsics::_getFloatAcquire: + case vmIntrinsics::_getDoubleAcquire: + case vmIntrinsics::_putReferenceRelease: + case vmIntrinsics::_putBooleanRelease: + case vmIntrinsics::_putByteRelease: + case vmIntrinsics::_putShortRelease: + case vmIntrinsics::_putCharRelease: + case vmIntrinsics::_putIntRelease: + case vmIntrinsics::_putLongRelease: + case vmIntrinsics::_putFloatRelease: + case vmIntrinsics::_putDoubleRelease: + case vmIntrinsics::_getReferenceOpaque: + case vmIntrinsics::_getBooleanOpaque: + case vmIntrinsics::_getByteOpaque: + case vmIntrinsics::_getShortOpaque: + case vmIntrinsics::_getCharOpaque: + case vmIntrinsics::_getIntOpaque: + case vmIntrinsics::_getLongOpaque: + case vmIntrinsics::_getFloatOpaque: + case vmIntrinsics::_getDoubleOpaque: + case vmIntrinsics::_putReferenceOpaque: + case vmIntrinsics::_putBooleanOpaque: + case vmIntrinsics::_putByteOpaque: + case vmIntrinsics::_putShortOpaque: + case vmIntrinsics::_putCharOpaque: + case vmIntrinsics::_putIntOpaque: + case vmIntrinsics::_putLongOpaque: + case vmIntrinsics::_putFloatOpaque: + case vmIntrinsics::_putDoubleOpaque: + case vmIntrinsics::_getAndAddInt: + case vmIntrinsics::_getAndAddLong: + case vmIntrinsics::_getAndSetInt: + case vmIntrinsics::_getAndSetLong: + case vmIntrinsics::_getAndSetReference: + case vmIntrinsics::_loadFence: + case vmIntrinsics::_storeFence: + case vmIntrinsics::_fullFence: + case vmIntrinsics::_compareAndSetLong: + case vmIntrinsics::_weakCompareAndSetLong: + case vmIntrinsics::_weakCompareAndSetLongPlain: + case vmIntrinsics::_weakCompareAndSetLongAcquire: + case vmIntrinsics::_weakCompareAndSetLongRelease: + case vmIntrinsics::_compareAndSetInt: + case vmIntrinsics::_weakCompareAndSetInt: + case vmIntrinsics::_weakCompareAndSetIntPlain: + case vmIntrinsics::_weakCompareAndSetIntAcquire: + case vmIntrinsics::_weakCompareAndSetIntRelease: + case vmIntrinsics::_compareAndSetReference: + case vmIntrinsics::_weakCompareAndSetReference: + case vmIntrinsics::_weakCompareAndSetReferencePlain: + case vmIntrinsics::_weakCompareAndSetReferenceAcquire: + case vmIntrinsics::_weakCompareAndSetReferenceRelease: + case vmIntrinsics::_compareAndExchangeInt: + case vmIntrinsics::_compareAndExchangeIntAcquire: + case vmIntrinsics::_compareAndExchangeIntRelease: + case vmIntrinsics::_compareAndExchangeLong: + case vmIntrinsics::_compareAndExchangeLongAcquire: + case vmIntrinsics::_compareAndExchangeLongRelease: + case vmIntrinsics::_compareAndExchangeReference: + case vmIntrinsics::_compareAndExchangeReferenceAcquire: + case vmIntrinsics::_compareAndExchangeReferenceRelease: + if (!InlineUnsafeOps) return true; + break; + case vmIntrinsics::_getShortUnaligned: + case vmIntrinsics::_getCharUnaligned: + case vmIntrinsics::_getIntUnaligned: + case vmIntrinsics::_getLongUnaligned: + case vmIntrinsics::_putShortUnaligned: + case vmIntrinsics::_putCharUnaligned: + case vmIntrinsics::_putIntUnaligned: + case vmIntrinsics::_putLongUnaligned: + case vmIntrinsics::_allocateInstance: + if (!InlineUnsafeOps || !UseUnalignedAccesses) return true; + break; + case vmIntrinsics::_hashCode: + if (!InlineObjectHash) return true; + break; + case vmIntrinsics::_aescrypt_encryptBlock: + case vmIntrinsics::_aescrypt_decryptBlock: + if (!UseAESIntrinsics) return true; + break; + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: + case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: + if (!UseAESIntrinsics) return true; + break; + case vmIntrinsics::_electronicCodeBook_encryptAESCrypt: + case vmIntrinsics::_electronicCodeBook_decryptAESCrypt: + if (!UseAESIntrinsics) return true; + break; + case vmIntrinsics::_counterMode_AESCrypt: + if (!UseAESCTRIntrinsics) return true; + break; + case vmIntrinsics::_md5_implCompress: + if (!UseMD5Intrinsics) return true; + break; + case vmIntrinsics::_sha_implCompress: + if (!UseSHA1Intrinsics) return true; + break; + case vmIntrinsics::_sha2_implCompress: + if (!UseSHA256Intrinsics) return true; + break; + case vmIntrinsics::_sha5_implCompress: + if (!UseSHA512Intrinsics) return true; + break; + case vmIntrinsics::_digestBase_implCompressMB: + if (!(UseMD5Intrinsics || UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return true; + break; + case vmIntrinsics::_ghash_processBlocks: + if (!UseGHASHIntrinsics) return true; + break; + case vmIntrinsics::_base64_encodeBlock: + if (!UseBASE64Intrinsics) return true; + break; + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: + if (!UseCRC32CIntrinsics) return true; + break; + case vmIntrinsics::_vectorizedMismatch: + if (!UseVectorizedMismatchIntrinsic) return true; + break; + case vmIntrinsics::_updateBytesAdler32: + case vmIntrinsics::_updateByteBufferAdler32: + if (!UseAdler32Intrinsics) return true; + break; + case vmIntrinsics::_copyMemory: + if (!InlineArrayCopy || !InlineUnsafeOps) return true; + break; +#ifdef COMPILER1 + case vmIntrinsics::_checkIndex: + if (!InlineNIOCheckIndex) return true; + break; +#endif // COMPILER1 +#ifdef COMPILER2 + case vmIntrinsics::_clone: + case vmIntrinsics::_copyOf: + case vmIntrinsics::_copyOfRange: + // These intrinsics use both the objectcopy and the arraycopy + // intrinsic mechanism. + if (!InlineObjectCopy || !InlineArrayCopy) return true; + break; + case vmIntrinsics::_compareToL: + case vmIntrinsics::_compareToU: + case vmIntrinsics::_compareToLU: + case vmIntrinsics::_compareToUL: + if (!SpecialStringCompareTo) return true; + break; + case vmIntrinsics::_indexOfL: + case vmIntrinsics::_indexOfU: + case vmIntrinsics::_indexOfUL: + case vmIntrinsics::_indexOfIL: + case vmIntrinsics::_indexOfIU: + case vmIntrinsics::_indexOfIUL: + case vmIntrinsics::_indexOfU_char: + if (!SpecialStringIndexOf) return true; + break; + case vmIntrinsics::_equalsL: + case vmIntrinsics::_equalsU: + if (!SpecialStringEquals) return true; + break; + case vmIntrinsics::_equalsB: + case vmIntrinsics::_equalsC: + if (!SpecialArraysEquals) return true; + break; + case vmIntrinsics::_encodeISOArray: + case vmIntrinsics::_encodeByteISOArray: + if (!SpecialEncodeISOArray) return true; + break; + case vmIntrinsics::_getCallerClass: + if (!InlineReflectionGetCallerClass) return true; + break; + case vmIntrinsics::_multiplyToLen: + if (!UseMultiplyToLenIntrinsic) return true; + break; + case vmIntrinsics::_squareToLen: + if (!UseSquareToLenIntrinsic) return true; + break; + case vmIntrinsics::_mulAdd: + if (!UseMulAddIntrinsic) return true; + break; + case vmIntrinsics::_montgomeryMultiply: + if (!UseMontgomeryMultiplyIntrinsic) return true; + break; + case vmIntrinsics::_montgomerySquare: + if (!UseMontgomerySquareIntrinsic) return true; + break; + case vmIntrinsics::_bigIntegerRightShiftWorker: + case vmIntrinsics::_bigIntegerLeftShiftWorker: + break; + case vmIntrinsics::_addExactI: + case vmIntrinsics::_addExactL: + case vmIntrinsics::_decrementExactI: + case vmIntrinsics::_decrementExactL: + case vmIntrinsics::_incrementExactI: + case vmIntrinsics::_incrementExactL: + case vmIntrinsics::_multiplyExactI: + case vmIntrinsics::_multiplyExactL: + case vmIntrinsics::_negateExactI: + case vmIntrinsics::_negateExactL: + case vmIntrinsics::_subtractExactI: + case vmIntrinsics::_subtractExactL: + if (!UseMathExactIntrinsics || !InlineMathNatives) return true; + break; + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: + if (!UseCharacterCompareIntrinsics) return true; + break; + case vmIntrinsics::_dcopySign: + case vmIntrinsics::_fcopySign: + if (!InlineMathNatives || !UseCopySignIntrinsic) return true; + break; + case vmIntrinsics::_dsignum: + case vmIntrinsics::_fsignum: + if (!InlineMathNatives || !UseSignumIntrinsic) return true; + break; +#endif // COMPILER2 + default: + return false; + } + + return false; +} + +#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" +static const char* vm_intrinsic_name_bodies = + VM_INTRINSICS_DO(VM_INTRINSIC_INITIALIZE, + VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); + +static const char* vm_intrinsic_name_table[vmIntrinsics::ID_LIMIT]; +static TriBoolArray<vmIntrinsics::ID_LIMIT, int> vm_intrinsic_control_words; + +static void init_vm_intrinsic_name_table() { + const char** nt = &vm_intrinsic_name_table[0]; + char* string = (char*) &vm_intrinsic_name_bodies[0]; + for (int index = vmIntrinsics::FIRST_ID; index < vmIntrinsics::ID_LIMIT; index++) { + nt[index] = string; + string += strlen(string); // skip string body + string += 1; // skip trailing null + } + assert(!strcmp(nt[vmIntrinsics::_hashCode], "_hashCode"), "lined up"); + nt[vmIntrinsics::_none] = "_none"; +} + +const char* vmIntrinsics::name_at(vmIntrinsics::ID id) { + const char** nt = &vm_intrinsic_name_table[0]; + if (nt[_none] == NULL) { + init_vm_intrinsic_name_table(); + } + + if ((uint)id < (uint)ID_LIMIT) + return vm_intrinsic_name_table[(uint)id]; + else + return "(unknown intrinsic)"; +} + +vmIntrinsics::ID vmIntrinsics::find_id(const char* name) { + const char** nt = &vm_intrinsic_name_table[0]; + if (nt[_none] == NULL) { + init_vm_intrinsic_name_table(); + } + + for (int index = FIRST_ID; index < ID_LIMIT; ++index) { + if (0 == strcmp(name, nt[index])) { + return ID_from(index); + } + } + + return _none; +} + +bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) { + vmIntrinsics::ID id = method->intrinsic_id(); + return is_disabled_by_flags(id); +} + +bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) { + assert(id > _none && id < ID_LIMIT, "must be a VM intrinsic"); + + // not initialized yet, process Control/DisableIntrinsic + if (vm_intrinsic_control_words[_none].is_default()) { + for (ControlIntrinsicIter iter(ControlIntrinsic); *iter != NULL; ++iter) { + vmIntrinsics::ID id = vmIntrinsics::find_id(*iter); + + if (id != vmIntrinsics::_none) { + vm_intrinsic_control_words[id] = iter.is_enabled() && !disabled_by_jvm_flags(id); + } + } + + // Order matters, DisableIntrinsic can overwrite ControlIntrinsic + for (ControlIntrinsicIter iter(DisableIntrinsic, true/*disable_all*/); *iter != NULL; ++iter) { + vmIntrinsics::ID id = vmIntrinsics::find_id(*iter); + + if (id != vmIntrinsics::_none) { + vm_intrinsic_control_words[id] = false; + } + } + + vm_intrinsic_control_words[_none] = true; + } + + TriBool b = vm_intrinsic_control_words[id]; + if (b.is_default()) { + // unknown yet, query and cache it + b = vm_intrinsic_control_words[id] = !disabled_by_jvm_flags(id); + } + + return !b; +} + +// These are for forming case labels: +#define ID3(x, y, z) (( jlong)(z) + \ + ((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \ + ((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) +#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) + +vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder, + vmSymbols::SID name, + vmSymbols::SID sig, + jshort flags) { + assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit"); + + // Let the C compiler build the decision tree. + +#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ + case ID3(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig)): \ + if (!match_##fcode(flags)) break; \ + return id; + + switch (ID3(holder, name, sig)) { + VM_INTRINSICS_DO(VM_INTRINSIC_CASE, + VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); + } + return vmIntrinsics::_none; + +#undef VM_INTRINSIC_CASE +} + + +const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf, int buflen) { + const char* str = name_at(id); +#ifndef PRODUCT + const char* kname = vmSymbols::name_for(class_for(id)); + const char* mname = vmSymbols::name_for(name_for(id)); + const char* sname = vmSymbols::name_for(signature_for(id)); + const char* fname = ""; + switch (flags_for(id)) { + case F_Y: fname = "synchronized "; break; + case F_RN: fname = "native "; break; + case F_SN: fname = "native static "; break; + case F_S: fname = "static "; break; + case F_RNY:fname = "native synchronized "; break; + default: break; + } + const char* kptr = strrchr(kname, JVM_SIGNATURE_SLASH); + if (kptr != NULL) kname = kptr + 1; + int len = jio_snprintf(buf, buflen, "%s: %s%s.%s%s", + str, fname, kname, mname, sname); + if (len < buflen) + str = buf; +#endif //PRODUCT + return str; +} + + +// These are to get information about intrinsics. + +#define ID4(x, y, z, f) ((ID3(x, y, z) << vmIntrinsics::log2_FLAG_LIMIT) | (jlong) (f)) + +static const jlong intrinsic_info_array[vmIntrinsics::ID_LIMIT+1] = { +#define VM_INTRINSIC_INFO(ignore_id, klass, name, sig, fcode) \ + ID4(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig), vmIntrinsics::fcode), + + 0, VM_INTRINSICS_DO(VM_INTRINSIC_INFO, + VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) + 0 +#undef VM_INTRINSIC_INFO +}; + +inline jlong intrinsic_info(vmIntrinsics::ID id) { + return intrinsic_info_array[vmIntrinsics::ID_from((int)id)]; +} + +vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) { + jlong info = intrinsic_info(id); + int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, ""); + return vmSymbols::SID( (info >> shift) & mask ); +} + +vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) { + jlong info = intrinsic_info(id); + int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, ""); + return vmSymbols::SID( (info >> shift) & mask ); +} + +vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) { + jlong info = intrinsic_info(id); + int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, ""); + return vmSymbols::SID( (info >> shift) & mask ); +} + +vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) { + jlong info = intrinsic_info(id); + int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, ""); + return Flags( (info >> shift) & mask ); +} + + +#ifndef PRODUCT +// verify_method performs an extra check on a matched intrinsic method + +static bool match_method(Method* m, Symbol* n, Symbol* s) { + return (m->name() == n && + m->signature() == s); +} + +static vmIntrinsics::ID match_method_with_klass(Method* m, Symbol* mk) { +#define VM_INTRINSIC_MATCH(id, klassname, namepart, sigpart, flags) \ + { Symbol* k = vmSymbols::klassname(); \ + if (mk == k) { \ + Symbol* n = vmSymbols::namepart(); \ + Symbol* s = vmSymbols::sigpart(); \ + if (match_method(m, n, s)) \ + return vmIntrinsics::id; \ + } } + VM_INTRINSICS_DO(VM_INTRINSIC_MATCH, + VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); + return vmIntrinsics::_none; +#undef VM_INTRINSIC_MATCH +} + +void vmIntrinsics::verify_method(ID actual_id, Method* m) { + Symbol* mk = m->method_holder()->name(); + ID declared_id = match_method_with_klass(m, mk); + + if (declared_id == actual_id) return; // success + + if (declared_id == _none && actual_id != _none && mk == vmSymbols::java_lang_StrictMath()) { + // Here are a few special cases in StrictMath not declared in vmSymbols.hpp. + switch (actual_id) { + case _min: + case _max: + case _dsqrt: + declared_id = match_method_with_klass(m, vmSymbols::java_lang_Math()); + if (declared_id == actual_id) return; // acceptable alias + break; + default: + break; + } + } + + const char* declared_name = name_at(declared_id); + const char* actual_name = name_at(actual_id); + m = NULL; + ttyLocker ttyl; + if (xtty != NULL) { + xtty->begin_elem("intrinsic_misdeclared actual='%s' declared='%s'", + actual_name, declared_name); + xtty->method(m); + xtty->end_elem("%s", ""); + } + if (PrintMiscellaneous && (WizardMode || Verbose)) { + tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):", + declared_name, declared_id, actual_name, actual_id); + m->print_short_name(tty); + tty->cr(); + } +} +#endif //PRODUCT diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp new file mode 100644 index 00000000000..7d4a76b6ee5 --- /dev/null +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -0,0 +1,873 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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_CLASSFILE_VMINTRINSICS_HPP +#define SHARE_CLASSFILE_VMINTRINSICS_HPP + +// Here are all the intrinsics known to the runtime and the CI. +// Each intrinsic consists of a public enum name (like _hashCode), +// followed by a specification of its klass, name, and signature: +// template(<id>, <klass>, <name>, <sig>, <FCODE>) +// +// If you add an intrinsic here, you must also define its name +// and signature as members of the VM symbols. The VM symbols for +// the intrinsic name and signature may be defined above. +// +// Because the VM_SYMBOLS_DO macro makes reference to VM_INTRINSICS_DO, +// you can also define an intrinsic's name and/or signature locally to the +// intrinsic, if this makes sense. (It often does make sense.) +// +// For example: +// do_intrinsic(_foo, java_lang_Object, foo_name, foo_signature, F_xx) +// do_name( foo_name, "foo") +// do_signature(foo_signature, "()F") +// klass = vmSymbols::java_lang_Object() +// name = vmSymbols::foo_name() +// signature = vmSymbols::foo_signature() +// +// The name and/or signature might be a "well known" symbol +// like "equal" or "()I", in which case there will be no local +// re-definition of the symbol. +// +// The do_class, do_name, and do_signature calls are all used for the +// same purpose: Define yet another VM symbol. They could all be merged +// into a common 'do_symbol' call, but it seems useful to record our +// intentions here about kinds of symbols (class vs. name vs. signature). +// +// The F_xx is one of the Flags enum; see below. +// +// for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t)) +// +// +// There are two types of intrinsic methods: (1) Library intrinsics and (2) bytecode intrinsics. +// +// (1) A library intrinsic method may be replaced with hand-crafted assembly code, +// with hand-crafted compiler IR, or with a combination of the two. The semantics +// of the replacement code may differ from the semantics of the replaced code. +// +// (2) Bytecode intrinsic methods are not replaced by special code, but they are +// treated in some other special way by the compiler. For example, the compiler +// may delay inlining for some String-related intrinsic methods (e.g., some methods +// defined in the StringBuilder and StringBuffer classes, see +// Compile::should_delay_string_inlining() for more details). +// +// Due to the difference between the semantics of an intrinsic method as defined +// in the (Java) source code and the semantics of the method as defined +// by the code in the VM, intrinsic methods must be explicitly marked. +// +// Intrinsic methods are marked by the jdk.internal.HotSpotIntrinsicCandidate +// annotation. If CheckIntrinsics is enabled, the VM performs the following +// checks when a class C is loaded: (1) all intrinsics defined by the VM for +// class C are present in the loaded class file and are marked; +// (2) an intrinsic is defined by the VM for all marked methods of class C; +// (3) check for orphan methods in class C (i.e., methods for which the VM +// declares an intrinsic but that are not declared for the loaded class C. +// Check (3) is available only in debug builds. +// +// If a mismatch is detected for a method, the VM behaves differently depending +// on the type of build. A fastdebug build exits and reports an error on a mismatch. +// A product build will not replace an unmarked library intrinsic method with +// hand-crafted code, that is, unmarked library intrinsics are treated as ordinary +// methods in a product build. The special treatment of a bytecode intrinsic method +// persists even if the method not marked. +// +// When adding an intrinsic for a method, please make sure to appropriately +// annotate the method in the source code. The list below contains all +// library intrinsics followed by bytecode intrinsics. Please also make sure to +// add the declaration of the intrinsic to the approriate section of the list. +#define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \ + /* (1) Library intrinsics */ \ + do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \ + do_name( hashCode_name, "hashCode") \ + do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \ + do_name( getClass_name, "getClass") \ + do_intrinsic(_clone, java_lang_Object, clone_name, void_object_signature, F_R) \ + do_name( clone_name, "clone") \ + do_intrinsic(_notify, java_lang_Object, notify_name, void_method_signature, F_R) \ + do_name( notify_name, "notify") \ + do_intrinsic(_notifyAll, java_lang_Object, notifyAll_name, void_method_signature, F_R) \ + do_name( notifyAll_name, "notifyAll") \ + \ + /* Math & StrictMath intrinsics are defined in terms of just a few signatures: */ \ + do_class(java_lang_Math, "java/lang/Math") \ + do_class(java_lang_StrictMath, "java/lang/StrictMath") \ + do_signature(double2_double_signature, "(DD)D") \ + do_signature(double3_double_signature, "(DDD)D") \ + do_signature(float2_float_signature, "(FF)F") \ + do_signature(float3_float_signature, "(FFF)F") \ + do_signature(int2_int_signature, "(II)I") \ + do_signature(long2_long_signature, "(JJ)J") \ + \ + /* here are the math names, all together: */ \ + do_name(abs_name,"abs") do_name(sin_name,"sin") do_name(cos_name,"cos") \ + do_name(tan_name,"tan") do_name(atan2_name,"atan2") do_name(sqrt_name,"sqrt") \ + do_name(log_name,"log") do_name(log10_name,"log10") do_name(pow_name,"pow") \ + do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \ + do_name(floor_name, "floor") do_name(ceil_name, "ceil") do_name(rint_name, "rint") \ + \ + do_name(addExact_name,"addExact") \ + do_name(decrementExact_name,"decrementExact") \ + do_name(incrementExact_name,"incrementExact") \ + do_name(multiplyExact_name,"multiplyExact") \ + do_name(multiplyHigh_name,"multiplyHigh") \ + do_name(negateExact_name,"negateExact") \ + do_name(subtractExact_name,"subtractExact") \ + do_name(fma_name, "fma") \ + do_name(copySign_name, "copySign") \ + do_name(signum_name,"signum") \ + \ + do_intrinsic(_dabs, java_lang_Math, abs_name, double_double_signature, F_S) \ + do_intrinsic(_fabs, java_lang_Math, abs_name, float_float_signature, F_S) \ + do_intrinsic(_iabs, java_lang_Math, abs_name, int_int_signature, F_S) \ + do_intrinsic(_labs, java_lang_Math, abs_name, long_long_signature, F_S) \ + do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \ + do_intrinsic(_floor, java_lang_Math, floor_name, double_double_signature, F_S) \ + do_intrinsic(_ceil, java_lang_Math, ceil_name, double_double_signature, F_S) \ + do_intrinsic(_rint, java_lang_Math, rint_name, double_double_signature, F_S) \ + do_intrinsic(_dcos, java_lang_Math, cos_name, double_double_signature, F_S) \ + do_intrinsic(_dtan, java_lang_Math, tan_name, double_double_signature, F_S) \ + do_intrinsic(_datan2, java_lang_Math, atan2_name, double2_double_signature, F_S) \ + do_intrinsic(_dsqrt, java_lang_Math, sqrt_name, double_double_signature, F_S) \ + do_intrinsic(_dlog, java_lang_Math, log_name, double_double_signature, F_S) \ + do_intrinsic(_dlog10, java_lang_Math, log10_name, double_double_signature, F_S) \ + do_intrinsic(_dpow, java_lang_Math, pow_name, double2_double_signature, F_S) \ + do_intrinsic(_dexp, java_lang_Math, exp_name, double_double_signature, F_S) \ + do_intrinsic(_min, java_lang_Math, min_name, int2_int_signature, F_S) \ + do_intrinsic(_max, java_lang_Math, max_name, int2_int_signature, F_S) \ + do_intrinsic(_addExactI, java_lang_Math, addExact_name, int2_int_signature, F_S) \ + do_intrinsic(_addExactL, java_lang_Math, addExact_name, long2_long_signature, F_S) \ + do_intrinsic(_decrementExactI, java_lang_Math, decrementExact_name, int_int_signature, F_S) \ + do_intrinsic(_decrementExactL, java_lang_Math, decrementExact_name, long_long_signature, F_S) \ + do_intrinsic(_incrementExactI, java_lang_Math, incrementExact_name, int_int_signature, F_S) \ + do_intrinsic(_incrementExactL, java_lang_Math, incrementExact_name, long_long_signature, F_S) \ + do_intrinsic(_multiplyExactI, java_lang_Math, multiplyExact_name, int2_int_signature, F_S) \ + do_intrinsic(_multiplyExactL, java_lang_Math, multiplyExact_name, long2_long_signature, F_S) \ + do_intrinsic(_multiplyHigh, java_lang_Math, multiplyHigh_name, long2_long_signature, F_S) \ + do_intrinsic(_negateExactI, java_lang_Math, negateExact_name, int_int_signature, F_S) \ + do_intrinsic(_negateExactL, java_lang_Math, negateExact_name, long_long_signature, F_S) \ + do_intrinsic(_subtractExactI, java_lang_Math, subtractExact_name, int2_int_signature, F_S) \ + do_intrinsic(_subtractExactL, java_lang_Math, subtractExact_name, long2_long_signature, F_S) \ + do_intrinsic(_fmaD, java_lang_Math, fma_name, double3_double_signature, F_S) \ + do_intrinsic(_fmaF, java_lang_Math, fma_name, float3_float_signature, F_S) \ + do_intrinsic(_maxF, java_lang_Math, max_name, float2_float_signature, F_S) \ + do_intrinsic(_minF, java_lang_Math, min_name, float2_float_signature, F_S) \ + do_intrinsic(_maxD, java_lang_Math, max_name, double2_double_signature, F_S) \ + do_intrinsic(_minD, java_lang_Math, min_name, double2_double_signature, F_S) \ + do_intrinsic(_dcopySign, java_lang_Math, copySign_name, double2_double_signature, F_S) \ + do_intrinsic(_fcopySign, java_lang_Math, copySign_name, float2_float_signature, F_S) \ + do_intrinsic(_dsignum, java_lang_Math, signum_name, double_double_signature, F_S) \ + do_intrinsic(_fsignum, java_lang_Math, signum_name, float_float_signature, F_S) \ + \ + do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_S) \ + do_name( floatToRawIntBits_name, "floatToRawIntBits") \ + do_intrinsic(_floatToIntBits, java_lang_Float, floatToIntBits_name, float_int_signature, F_S) \ + do_name( floatToIntBits_name, "floatToIntBits") \ + do_intrinsic(_intBitsToFloat, java_lang_Float, intBitsToFloat_name, int_float_signature, F_S) \ + do_name( intBitsToFloat_name, "intBitsToFloat") \ + do_intrinsic(_doubleToRawLongBits, java_lang_Double, doubleToRawLongBits_name, double_long_signature, F_S) \ + do_name( doubleToRawLongBits_name, "doubleToRawLongBits") \ + do_intrinsic(_doubleToLongBits, java_lang_Double, doubleToLongBits_name, double_long_signature, F_S) \ + do_name( doubleToLongBits_name, "doubleToLongBits") \ + do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \ + do_name( longBitsToDouble_name, "longBitsToDouble") \ + \ + do_intrinsic(_numberOfLeadingZeros_i, java_lang_Integer, numberOfLeadingZeros_name,int_int_signature, F_S) \ + do_intrinsic(_numberOfLeadingZeros_l, java_lang_Long, numberOfLeadingZeros_name,long_int_signature, F_S) \ + \ + do_intrinsic(_numberOfTrailingZeros_i, java_lang_Integer, numberOfTrailingZeros_name,int_int_signature, F_S) \ + do_intrinsic(_numberOfTrailingZeros_l, java_lang_Long, numberOfTrailingZeros_name,long_int_signature, F_S) \ + \ + do_intrinsic(_bitCount_i, java_lang_Integer, bitCount_name, int_int_signature, F_S) \ + do_intrinsic(_bitCount_l, java_lang_Long, bitCount_name, long_int_signature, F_S) \ + \ + do_intrinsic(_reverseBytes_i, java_lang_Integer, reverseBytes_name, int_int_signature, F_S) \ + do_name( reverseBytes_name, "reverseBytes") \ + do_intrinsic(_reverseBytes_l, java_lang_Long, reverseBytes_name, long_long_signature, F_S) \ + /* (symbol reverseBytes_name defined above) */ \ + do_intrinsic(_reverseBytes_c, java_lang_Character, reverseBytes_name, char_char_signature, F_S) \ + /* (symbol reverseBytes_name defined above) */ \ + do_intrinsic(_reverseBytes_s, java_lang_Short, reverseBytes_name, short_short_signature, F_S) \ + /* (symbol reverseBytes_name defined above) */ \ + \ + do_intrinsic(_identityHashCode, java_lang_System, identityHashCode_name, object_int_signature, F_S) \ + do_name( identityHashCode_name, "identityHashCode") \ + do_intrinsic(_currentTimeMillis, java_lang_System, currentTimeMillis_name, void_long_signature, F_S) \ + \ + do_name( currentTimeMillis_name, "currentTimeMillis") \ + do_intrinsic(_nanoTime, java_lang_System, nanoTime_name, void_long_signature, F_S) \ + do_name( nanoTime_name, "nanoTime") \ + \ + JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \ + \ + do_intrinsic(_arraycopy, java_lang_System, arraycopy_name, arraycopy_signature, F_S) \ + do_name( arraycopy_name, "arraycopy") \ + do_signature(arraycopy_signature, "(Ljava/lang/Object;ILjava/lang/Object;II)V") \ + do_intrinsic(_currentThread, java_lang_Thread, currentThread_name, currentThread_signature, F_S) \ + do_name( currentThread_name, "currentThread") \ + do_signature(currentThread_signature, "()Ljava/lang/Thread;") \ + \ + /* reflective intrinsics, for java/lang/Class, etc. */ \ + do_intrinsic(_isAssignableFrom, java_lang_Class, isAssignableFrom_name, class_boolean_signature, F_RN) \ + do_name( isAssignableFrom_name, "isAssignableFrom") \ + do_intrinsic(_isInstance, java_lang_Class, isInstance_name, object_boolean_signature, F_RN) \ + do_name( isInstance_name, "isInstance") \ + do_intrinsic(_getModifiers, java_lang_Class, getModifiers_name, void_int_signature, F_RN) \ + do_name( getModifiers_name, "getModifiers") \ + do_intrinsic(_isInterface, java_lang_Class, isInterface_name, void_boolean_signature, F_RN) \ + do_name( isInterface_name, "isInterface") \ + do_intrinsic(_isArray, java_lang_Class, isArray_name, void_boolean_signature, F_RN) \ + do_name( isArray_name, "isArray") \ + do_intrinsic(_isPrimitive, java_lang_Class, isPrimitive_name, void_boolean_signature, F_RN) \ + do_name( isPrimitive_name, "isPrimitive") \ + do_intrinsic(_isHidden, java_lang_Class, isHidden_name, void_boolean_signature, F_RN) \ + do_name( isHidden_name, "isHidden") \ + do_intrinsic(_getSuperclass, java_lang_Class, getSuperclass_name, void_class_signature, F_RN) \ + do_name( getSuperclass_name, "getSuperclass") \ + do_intrinsic(_Class_cast, java_lang_Class, Class_cast_name, object_object_signature, F_R) \ + do_name( Class_cast_name, "cast") \ + \ + do_intrinsic(_getClassAccessFlags, reflect_Reflection, getClassAccessFlags_name, class_int_signature, F_SN) \ + do_name( getClassAccessFlags_name, "getClassAccessFlags") \ + do_intrinsic(_getLength, java_lang_reflect_Array, getLength_name, object_int_signature, F_SN) \ + do_name( getLength_name, "getLength") \ + \ + do_intrinsic(_getCallerClass, reflect_Reflection, getCallerClass_name, void_class_signature, F_SN) \ + do_name( getCallerClass_name, "getCallerClass") \ + \ + do_intrinsic(_newArray, java_lang_reflect_Array, newArray_name, newArray_signature, F_SN) \ + do_name( newArray_name, "newArray") \ + do_signature(newArray_signature, "(Ljava/lang/Class;I)Ljava/lang/Object;") \ + \ + do_intrinsic(_onSpinWait, java_lang_Thread, onSpinWait_name, onSpinWait_signature, F_S) \ + do_name( onSpinWait_name, "onSpinWait") \ + do_alias( onSpinWait_signature, void_method_signature) \ + \ + do_intrinsic(_copyOf, java_util_Arrays, copyOf_name, copyOf_signature, F_S) \ + do_name( copyOf_name, "copyOf") \ + do_signature(copyOf_signature, "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;") \ + \ + do_intrinsic(_copyOfRange, java_util_Arrays, copyOfRange_name, copyOfRange_signature, F_S) \ + do_name( copyOfRange_name, "copyOfRange") \ + do_signature(copyOfRange_signature, "([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;") \ + \ + do_intrinsic(_equalsC, java_util_Arrays, equals_name, equalsC_signature, F_S) \ + do_signature(equalsC_signature, "([C[C)Z") \ + do_intrinsic(_equalsB, java_util_Arrays, equals_name, equalsB_signature, F_S) \ + do_signature(equalsB_signature, "([B[B)Z") \ + \ + do_intrinsic(_compressStringC, java_lang_StringUTF16, compress_name, encodeISOArray_signature, F_S) \ + do_name( compress_name, "compress") \ + do_intrinsic(_compressStringB, java_lang_StringUTF16, compress_name, indexOfI_signature, F_S) \ + do_intrinsic(_inflateStringC, java_lang_StringLatin1, inflate_name, inflateC_signature, F_S) \ + do_name( inflate_name, "inflate") \ + do_signature(inflateC_signature, "([BI[CII)V") \ + do_intrinsic(_inflateStringB, java_lang_StringLatin1, inflate_name, inflateB_signature, F_S) \ + do_signature(inflateB_signature, "([BI[BII)V") \ + do_intrinsic(_toBytesStringU, java_lang_StringUTF16, toBytes_name, toBytesU_signature, F_S) \ + do_name( toBytes_name, "toBytes") \ + do_signature(toBytesU_signature, "([CII)[B") \ + do_intrinsic(_getCharsStringU, java_lang_StringUTF16, getCharsU_name, getCharsU_signature, F_S) \ + do_name( getCharsU_name, "getChars") \ + do_signature(getCharsU_signature, "([BII[CI)V") \ + do_intrinsic(_getCharStringU, java_lang_StringUTF16, getChar_name, getCharStringU_signature, F_S) \ + do_signature(getCharStringU_signature, "([BI)C") \ + do_intrinsic(_putCharStringU, java_lang_StringUTF16, putChar_name, putCharStringU_signature, F_S) \ + do_signature(putCharStringU_signature, "([BII)V") \ + do_intrinsic(_compareToL, java_lang_StringLatin1,compareTo_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_compareToU, java_lang_StringUTF16, compareTo_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_compareToLU, java_lang_StringLatin1,compareToLU_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_compareToUL, java_lang_StringUTF16, compareToUL_name, compareTo_indexOf_signature, F_S) \ + do_signature(compareTo_indexOf_signature, "([B[B)I") \ + do_name( compareTo_name, "compareTo") \ + do_name( compareToLU_name, "compareToUTF16") \ + do_name( compareToUL_name, "compareToLatin1") \ + do_intrinsic(_indexOfL, java_lang_StringLatin1,indexOf_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_indexOfU, java_lang_StringUTF16, indexOf_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_indexOfUL, java_lang_StringUTF16, indexOfUL_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_indexOfIL, java_lang_StringLatin1,indexOf_name, indexOfI_signature, F_S) \ + do_intrinsic(_indexOfIU, java_lang_StringUTF16, indexOf_name, indexOfI_signature, F_S) \ + do_intrinsic(_indexOfIUL, java_lang_StringUTF16, indexOfUL_name, indexOfI_signature, F_S) \ + do_intrinsic(_indexOfU_char, java_lang_StringUTF16, indexOfChar_name, indexOfChar_signature, F_S) \ + do_name( indexOf_name, "indexOf") \ + do_name( indexOfChar_name, "indexOfChar") \ + do_name( indexOfUL_name, "indexOfLatin1") \ + do_signature(indexOfI_signature, "([BI[BII)I") \ + do_signature(indexOfChar_signature, "([BIII)I") \ + do_intrinsic(_equalsL, java_lang_StringLatin1,equals_name, equalsB_signature, F_S) \ + do_intrinsic(_equalsU, java_lang_StringUTF16, equals_name, equalsB_signature, F_S) \ + \ + do_intrinsic(_isDigit, java_lang_CharacterDataLatin1, isDigit_name, int_bool_signature, F_R) \ + do_name( isDigit_name, "isDigit") \ + do_intrinsic(_isLowerCase, java_lang_CharacterDataLatin1, isLowerCase_name, int_bool_signature, F_R) \ + do_name( isLowerCase_name, "isLowerCase") \ + do_intrinsic(_isUpperCase, java_lang_CharacterDataLatin1, isUpperCase_name, int_bool_signature, F_R) \ + do_name( isUpperCase_name, "isUpperCase") \ + do_intrinsic(_isWhitespace, java_lang_CharacterDataLatin1, isWhitespace_name, int_bool_signature, F_R) \ + do_name( isWhitespace_name, "isWhitespace") \ + \ + do_intrinsic(_Preconditions_checkIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkIndex_signature, F_S) \ + do_signature(Preconditions_checkIndex_signature, "(IILjava/util/function/BiFunction;)I") \ + \ + do_class(java_nio_Buffer, "java/nio/Buffer") \ + do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \ + do_name( checkIndex_name, "checkIndex") \ + \ + do_class(java_lang_StringCoding, "java/lang/StringCoding") \ + do_intrinsic(_hasNegatives, java_lang_StringCoding, hasNegatives_name, hasNegatives_signature, F_S) \ + do_name( hasNegatives_name, "hasNegatives") \ + do_signature(hasNegatives_signature, "([BII)Z") \ + \ + do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ + do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ + do_name( encodeISOArray_name, "implEncodeISOArray") \ + do_signature(encodeISOArray_signature, "([CI[BII)I") \ + \ + do_intrinsic(_encodeByteISOArray, java_lang_StringCoding, encodeISOArray_name, indexOfI_signature, F_S) \ + \ + do_class(java_math_BigInteger, "java/math/BigInteger") \ + do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \ + do_name( multiplyToLen_name, "implMultiplyToLen") \ + do_signature(multiplyToLen_signature, "([II[II[I)[I") \ + \ + do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \ + do_name( squareToLen_name, "implSquareToLen") \ + do_signature(squareToLen_signature, "([II[II)[I") \ + \ + do_intrinsic(_mulAdd, java_math_BigInteger, mulAdd_name, mulAdd_signature, F_S) \ + do_name( mulAdd_name, "implMulAdd") \ + do_signature(mulAdd_signature, "([I[IIII)I") \ + \ + do_intrinsic(_montgomeryMultiply, java_math_BigInteger, montgomeryMultiply_name, montgomeryMultiply_signature, F_S) \ + do_name( montgomeryMultiply_name, "implMontgomeryMultiply") \ + do_signature(montgomeryMultiply_signature, "([I[I[IIJ[I)[I") \ + \ + do_intrinsic(_montgomerySquare, java_math_BigInteger, montgomerySquare_name, montgomerySquare_signature, F_S) \ + do_name( montgomerySquare_name, "implMontgomerySquare") \ + do_signature(montgomerySquare_signature, "([I[IIJ[I)[I") \ + \ + do_intrinsic(_bigIntegerRightShiftWorker, java_math_BigInteger, rightShift_name, big_integer_shift_worker_signature, F_S) \ + do_name( rightShift_name, "shiftRightImplWorker") \ + \ + do_intrinsic(_bigIntegerLeftShiftWorker, java_math_BigInteger, leftShift_name, big_integer_shift_worker_signature, F_S) \ + do_name( leftShift_name, "shiftLeftImplWorker") \ + \ + do_class(jdk_internal_util_ArraysSupport, "jdk/internal/util/ArraysSupport") \ + do_intrinsic(_vectorizedMismatch, jdk_internal_util_ArraysSupport, vectorizedMismatch_name, vectorizedMismatch_signature, F_S)\ + do_name(vectorizedMismatch_name, "vectorizedMismatch") \ + do_signature(vectorizedMismatch_signature, "(Ljava/lang/Object;JLjava/lang/Object;JII)I") \ + \ + /* java/lang/ref/Reference */ \ + do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ + \ + /* support for com.sun.crypto.provider.AESCrypt and some of its callers */ \ + do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \ + do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ + do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ + do_name( encryptBlock_name, "implEncryptBlock") \ + do_name( decryptBlock_name, "implDecryptBlock") \ + do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \ + \ + do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \ + do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ + do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ + do_name( encrypt_name, "implEncrypt") \ + do_name( decrypt_name, "implDecrypt") \ + do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \ + \ + do_class(com_sun_crypto_provider_electronicCodeBook, "com/sun/crypto/provider/ElectronicCodeBook") \ + do_intrinsic(_electronicCodeBook_encryptAESCrypt, com_sun_crypto_provider_electronicCodeBook, ecb_encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ + do_intrinsic(_electronicCodeBook_decryptAESCrypt, com_sun_crypto_provider_electronicCodeBook, ecb_decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ + do_name(ecb_encrypt_name, "implECBEncrypt") \ + do_name(ecb_decrypt_name, "implECBDecrypt") \ + \ + do_class(com_sun_crypto_provider_counterMode, "com/sun/crypto/provider/CounterMode") \ + do_intrinsic(_counterMode_AESCrypt, com_sun_crypto_provider_counterMode, crypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ + do_name( crypt_name, "implCrypt") \ + \ + /* support for sun.security.provider.MD5 */ \ + do_class(sun_security_provider_md5, "sun/security/provider/MD5") \ + do_intrinsic(_md5_implCompress, sun_security_provider_md5, implCompress_name, implCompress_signature, F_R) \ + do_name( implCompress_name, "implCompress0") \ + do_signature(implCompress_signature, "([BI)V") \ + \ + /* support for sun.security.provider.SHA */ \ + do_class(sun_security_provider_sha, "sun/security/provider/SHA") \ + do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \ + \ + /* support for sun.security.provider.SHA2 */ \ + do_class(sun_security_provider_sha2, "sun/security/provider/SHA2") \ + do_intrinsic(_sha2_implCompress, sun_security_provider_sha2, implCompress_name, implCompress_signature, F_R) \ + \ + /* support for sun.security.provider.SHA5 */ \ + do_class(sun_security_provider_sha5, "sun/security/provider/SHA5") \ + do_intrinsic(_sha5_implCompress, sun_security_provider_sha5, implCompress_name, implCompress_signature, F_R) \ + \ + /* support for sun.security.provider.DigestBase */ \ + do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \ + do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \ + do_name( implCompressMB_name, "implCompressMultiBlock0") \ + do_signature(implCompressMB_signature, "([BII)I") \ + \ + /* support for java.util.Base64.Encoder*/ \ + do_class(java_util_Base64_Encoder, "java/util/Base64$Encoder") \ + do_intrinsic(_base64_encodeBlock, java_util_Base64_Encoder, encodeBlock_name, encodeBlock_signature, F_R) \ + do_name(encodeBlock_name, "encodeBlock") \ + do_signature(encodeBlock_signature, "([BII[BIZ)V") \ + \ + /* support for com.sun.crypto.provider.GHASH */ \ + do_class(com_sun_crypto_provider_ghash, "com/sun/crypto/provider/GHASH") \ + do_intrinsic(_ghash_processBlocks, com_sun_crypto_provider_ghash, processBlocks_name, ghash_processBlocks_signature, F_S) \ + do_name(processBlocks_name, "processBlocks") \ + do_signature(ghash_processBlocks_signature, "([BII[J[J)V") \ + \ + /* support for java.util.zip */ \ + do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \ + do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \ + do_name( update_name, "update") \ + do_intrinsic(_updateBytesCRC32, java_util_zip_CRC32, updateBytes_name, updateBytes_signature, F_SN) \ + do_name( updateBytes_name, "updateBytes0") \ + do_signature(updateBytes_signature, "(I[BII)I") \ + do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \ + do_name( updateByteBuffer_name, "updateByteBuffer0") \ + do_signature(updateByteBuffer_signature, "(IJII)I") \ + \ + /* support for java.util.zip.CRC32C */ \ + do_class(java_util_zip_CRC32C, "java/util/zip/CRC32C") \ + do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_C_name, updateBytes_signature, F_S) \ + do_name( updateBytes_C_name, "updateBytes") \ + do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_C_name, updateByteBuffer_signature, F_S) \ + do_name( updateDirectByteBuffer_C_name, "updateDirectByteBuffer") \ + \ + /* support for java.util.zip.Adler32 */ \ + do_class(java_util_zip_Adler32, "java/util/zip/Adler32") \ + do_intrinsic(_updateBytesAdler32, java_util_zip_Adler32, updateBytes_C_name, updateBytes_signature, F_SN) \ + do_intrinsic(_updateByteBufferAdler32, java_util_zip_Adler32, updateByteBuffer_A_name, updateByteBuffer_signature, F_SN) \ + do_name( updateByteBuffer_A_name, "updateByteBuffer") \ + \ + /* support for UnsafeConstants */ \ + do_class(jdk_internal_misc_UnsafeConstants, "jdk/internal/misc/UnsafeConstants") \ + \ + /* support for Unsafe */ \ + do_class(jdk_internal_misc_Unsafe, "jdk/internal/misc/Unsafe") \ + do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ + \ + do_intrinsic(_writeback0, jdk_internal_misc_Unsafe, writeback0_name, long_void_signature , F_RN) \ + do_name( writeback0_name, "writeback0") \ + do_intrinsic(_writebackPreSync0, jdk_internal_misc_Unsafe, writebackPreSync0_name, void_method_signature , F_RN) \ + do_name( writebackPreSync0_name, "writebackPreSync0") \ + do_intrinsic(_writebackPostSync0, jdk_internal_misc_Unsafe, writebackPostSync0_name, void_method_signature , F_RN) \ + do_name( writebackPostSync0_name, "writebackPostSync0") \ + do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \ + do_name( allocateInstance_name, "allocateInstance") \ + do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \ + do_intrinsic(_allocateUninitializedArray, jdk_internal_misc_Unsafe, allocateUninitializedArray_name, newArray_signature, F_R) \ + do_name( allocateUninitializedArray_name, "allocateUninitializedArray0") \ + do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ + do_name( copyMemory_name, "copyMemory0") \ + do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ + do_intrinsic(_loadFence, jdk_internal_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ + do_name( loadFence_name, "loadFence") \ + do_alias( loadFence_signature, void_method_signature) \ + do_intrinsic(_storeFence, jdk_internal_misc_Unsafe, storeFence_name, storeFence_signature, F_RN) \ + do_name( storeFence_name, "storeFence") \ + do_alias( storeFence_signature, void_method_signature) \ + do_intrinsic(_fullFence, jdk_internal_misc_Unsafe, fullFence_name, fullFence_signature, F_RN) \ + do_name( fullFence_name, "fullFence") \ + do_alias( fullFence_signature, void_method_signature) \ + \ + /* Custom branch frequencies profiling support for JSR292 */ \ + do_class(java_lang_invoke_MethodHandleImpl, "java/lang/invoke/MethodHandleImpl") \ + do_intrinsic(_profileBoolean, java_lang_invoke_MethodHandleImpl, profileBoolean_name, profileBoolean_signature, F_S) \ + do_name( profileBoolean_name, "profileBoolean") \ + do_signature(profileBoolean_signature, "(Z[I)Z") \ + do_intrinsic(_isCompileConstant, java_lang_invoke_MethodHandleImpl, isCompileConstant_name, isCompileConstant_signature, F_S) \ + do_name( isCompileConstant_name, "isCompileConstant") \ + do_alias( isCompileConstant_signature, object_boolean_signature) \ + \ + /* unsafe memory references (there are a lot of them...) */ \ + do_signature(getReference_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \ + do_signature(putReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \ + do_signature(getBoolean_signature, "(Ljava/lang/Object;J)Z") \ + do_signature(putBoolean_signature, "(Ljava/lang/Object;JZ)V") \ + do_signature(getByte_signature, "(Ljava/lang/Object;J)B") \ + do_signature(putByte_signature, "(Ljava/lang/Object;JB)V") \ + do_signature(getShort_signature, "(Ljava/lang/Object;J)S") \ + do_signature(putShort_signature, "(Ljava/lang/Object;JS)V") \ + do_signature(getChar_signature, "(Ljava/lang/Object;J)C") \ + do_signature(putChar_signature, "(Ljava/lang/Object;JC)V") \ + do_signature(getInt_signature, "(Ljava/lang/Object;J)I") \ + do_signature(putInt_signature, "(Ljava/lang/Object;JI)V") \ + do_signature(getLong_signature, "(Ljava/lang/Object;J)J") \ + do_signature(putLong_signature, "(Ljava/lang/Object;JJ)V") \ + do_signature(getFloat_signature, "(Ljava/lang/Object;J)F") \ + do_signature(putFloat_signature, "(Ljava/lang/Object;JF)V") \ + do_signature(getDouble_signature, "(Ljava/lang/Object;J)D") \ + do_signature(putDouble_signature, "(Ljava/lang/Object;JD)V") \ + \ + do_name(getReference_name,"getReference") do_name(putReference_name,"putReference") \ + do_name(getBoolean_name,"getBoolean") do_name(putBoolean_name,"putBoolean") \ + do_name(getByte_name,"getByte") do_name(putByte_name,"putByte") \ + do_name(getShort_name,"getShort") do_name(putShort_name,"putShort") \ + do_name(getChar_name,"getChar") do_name(putChar_name,"putChar") \ + do_name(getInt_name,"getInt") do_name(putInt_name,"putInt") \ + do_name(getLong_name,"getLong") do_name(putLong_name,"putLong") \ + do_name(getFloat_name,"getFloat") do_name(putFloat_name,"putFloat") \ + do_name(getDouble_name,"getDouble") do_name(putDouble_name,"putDouble") \ + \ + do_intrinsic(_getReference, jdk_internal_misc_Unsafe, getReference_name, getReference_signature, F_RN) \ + do_intrinsic(_getBoolean, jdk_internal_misc_Unsafe, getBoolean_name, getBoolean_signature, F_RN) \ + do_intrinsic(_getByte, jdk_internal_misc_Unsafe, getByte_name, getByte_signature, F_RN) \ + do_intrinsic(_getShort, jdk_internal_misc_Unsafe, getShort_name, getShort_signature, F_RN) \ + do_intrinsic(_getChar, jdk_internal_misc_Unsafe, getChar_name, getChar_signature, F_RN) \ + do_intrinsic(_getInt, jdk_internal_misc_Unsafe, getInt_name, getInt_signature, F_RN) \ + do_intrinsic(_getLong, jdk_internal_misc_Unsafe, getLong_name, getLong_signature, F_RN) \ + do_intrinsic(_getFloat, jdk_internal_misc_Unsafe, getFloat_name, getFloat_signature, F_RN) \ + do_intrinsic(_getDouble, jdk_internal_misc_Unsafe, getDouble_name, getDouble_signature, F_RN) \ + do_intrinsic(_putReference, jdk_internal_misc_Unsafe, putReference_name, putReference_signature, F_RN) \ + do_intrinsic(_putBoolean, jdk_internal_misc_Unsafe, putBoolean_name, putBoolean_signature, F_RN) \ + do_intrinsic(_putByte, jdk_internal_misc_Unsafe, putByte_name, putByte_signature, F_RN) \ + do_intrinsic(_putShort, jdk_internal_misc_Unsafe, putShort_name, putShort_signature, F_RN) \ + do_intrinsic(_putChar, jdk_internal_misc_Unsafe, putChar_name, putChar_signature, F_RN) \ + do_intrinsic(_putInt, jdk_internal_misc_Unsafe, putInt_name, putInt_signature, F_RN) \ + do_intrinsic(_putLong, jdk_internal_misc_Unsafe, putLong_name, putLong_signature, F_RN) \ + do_intrinsic(_putFloat, jdk_internal_misc_Unsafe, putFloat_name, putFloat_signature, F_RN) \ + do_intrinsic(_putDouble, jdk_internal_misc_Unsafe, putDouble_name, putDouble_signature, F_RN) \ + \ + do_name(getReferenceVolatile_name,"getReferenceVolatile") do_name(putReferenceVolatile_name,"putReferenceVolatile") \ + do_name(getBooleanVolatile_name,"getBooleanVolatile") do_name(putBooleanVolatile_name,"putBooleanVolatile") \ + do_name(getByteVolatile_name,"getByteVolatile") do_name(putByteVolatile_name,"putByteVolatile") \ + do_name(getShortVolatile_name,"getShortVolatile") do_name(putShortVolatile_name,"putShortVolatile") \ + do_name(getCharVolatile_name,"getCharVolatile") do_name(putCharVolatile_name,"putCharVolatile") \ + do_name(getIntVolatile_name,"getIntVolatile") do_name(putIntVolatile_name,"putIntVolatile") \ + do_name(getLongVolatile_name,"getLongVolatile") do_name(putLongVolatile_name,"putLongVolatile") \ + do_name(getFloatVolatile_name,"getFloatVolatile") do_name(putFloatVolatile_name,"putFloatVolatile") \ + do_name(getDoubleVolatile_name,"getDoubleVolatile") do_name(putDoubleVolatile_name,"putDoubleVolatile") \ + \ + do_intrinsic(_getReferenceVolatile, jdk_internal_misc_Unsafe, getReferenceVolatile_name, getReference_signature, F_RN) \ + do_intrinsic(_getBooleanVolatile, jdk_internal_misc_Unsafe, getBooleanVolatile_name, getBoolean_signature, F_RN) \ + do_intrinsic(_getByteVolatile, jdk_internal_misc_Unsafe, getByteVolatile_name, getByte_signature, F_RN) \ + do_intrinsic(_getShortVolatile, jdk_internal_misc_Unsafe, getShortVolatile_name, getShort_signature, F_RN) \ + do_intrinsic(_getCharVolatile, jdk_internal_misc_Unsafe, getCharVolatile_name, getChar_signature, F_RN) \ + do_intrinsic(_getIntVolatile, jdk_internal_misc_Unsafe, getIntVolatile_name, getInt_signature, F_RN) \ + do_intrinsic(_getLongVolatile, jdk_internal_misc_Unsafe, getLongVolatile_name, getLong_signature, F_RN) \ + do_intrinsic(_getFloatVolatile, jdk_internal_misc_Unsafe, getFloatVolatile_name, getFloat_signature, F_RN) \ + do_intrinsic(_getDoubleVolatile, jdk_internal_misc_Unsafe, getDoubleVolatile_name, getDouble_signature, F_RN) \ + do_intrinsic(_putReferenceVolatile, jdk_internal_misc_Unsafe, putReferenceVolatile_name, putReference_signature, F_RN) \ + do_intrinsic(_putBooleanVolatile, jdk_internal_misc_Unsafe, putBooleanVolatile_name, putBoolean_signature, F_RN) \ + do_intrinsic(_putByteVolatile, jdk_internal_misc_Unsafe, putByteVolatile_name, putByte_signature, F_RN) \ + do_intrinsic(_putShortVolatile, jdk_internal_misc_Unsafe, putShortVolatile_name, putShort_signature, F_RN) \ + do_intrinsic(_putCharVolatile, jdk_internal_misc_Unsafe, putCharVolatile_name, putChar_signature, F_RN) \ + do_intrinsic(_putIntVolatile, jdk_internal_misc_Unsafe, putIntVolatile_name, putInt_signature, F_RN) \ + do_intrinsic(_putLongVolatile, jdk_internal_misc_Unsafe, putLongVolatile_name, putLong_signature, F_RN) \ + do_intrinsic(_putFloatVolatile, jdk_internal_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \ + do_intrinsic(_putDoubleVolatile, jdk_internal_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \ + \ + do_name(getReferenceOpaque_name,"getReferenceOpaque") do_name(putReferenceOpaque_name,"putReferenceOpaque") \ + do_name(getBooleanOpaque_name,"getBooleanOpaque") do_name(putBooleanOpaque_name,"putBooleanOpaque") \ + do_name(getByteOpaque_name,"getByteOpaque") do_name(putByteOpaque_name,"putByteOpaque") \ + do_name(getShortOpaque_name,"getShortOpaque") do_name(putShortOpaque_name,"putShortOpaque") \ + do_name(getCharOpaque_name,"getCharOpaque") do_name(putCharOpaque_name,"putCharOpaque") \ + do_name(getIntOpaque_name,"getIntOpaque") do_name(putIntOpaque_name,"putIntOpaque") \ + do_name(getLongOpaque_name,"getLongOpaque") do_name(putLongOpaque_name,"putLongOpaque") \ + do_name(getFloatOpaque_name,"getFloatOpaque") do_name(putFloatOpaque_name,"putFloatOpaque") \ + do_name(getDoubleOpaque_name,"getDoubleOpaque") do_name(putDoubleOpaque_name,"putDoubleOpaque") \ + \ + do_intrinsic(_getReferenceOpaque, jdk_internal_misc_Unsafe, getReferenceOpaque_name, getReference_signature, F_R) \ + do_intrinsic(_getBooleanOpaque, jdk_internal_misc_Unsafe, getBooleanOpaque_name, getBoolean_signature, F_R) \ + do_intrinsic(_getByteOpaque, jdk_internal_misc_Unsafe, getByteOpaque_name, getByte_signature, F_R) \ + do_intrinsic(_getShortOpaque, jdk_internal_misc_Unsafe, getShortOpaque_name, getShort_signature, F_R) \ + do_intrinsic(_getCharOpaque, jdk_internal_misc_Unsafe, getCharOpaque_name, getChar_signature, F_R) \ + do_intrinsic(_getIntOpaque, jdk_internal_misc_Unsafe, getIntOpaque_name, getInt_signature, F_R) \ + do_intrinsic(_getLongOpaque, jdk_internal_misc_Unsafe, getLongOpaque_name, getLong_signature, F_R) \ + do_intrinsic(_getFloatOpaque, jdk_internal_misc_Unsafe, getFloatOpaque_name, getFloat_signature, F_R) \ + do_intrinsic(_getDoubleOpaque, jdk_internal_misc_Unsafe, getDoubleOpaque_name, getDouble_signature, F_R) \ + do_intrinsic(_putReferenceOpaque, jdk_internal_misc_Unsafe, putReferenceOpaque_name, putReference_signature, F_R) \ + do_intrinsic(_putBooleanOpaque, jdk_internal_misc_Unsafe, putBooleanOpaque_name, putBoolean_signature, F_R) \ + do_intrinsic(_putByteOpaque, jdk_internal_misc_Unsafe, putByteOpaque_name, putByte_signature, F_R) \ + do_intrinsic(_putShortOpaque, jdk_internal_misc_Unsafe, putShortOpaque_name, putShort_signature, F_R) \ + do_intrinsic(_putCharOpaque, jdk_internal_misc_Unsafe, putCharOpaque_name, putChar_signature, F_R) \ + do_intrinsic(_putIntOpaque, jdk_internal_misc_Unsafe, putIntOpaque_name, putInt_signature, F_R) \ + do_intrinsic(_putLongOpaque, jdk_internal_misc_Unsafe, putLongOpaque_name, putLong_signature, F_R) \ + do_intrinsic(_putFloatOpaque, jdk_internal_misc_Unsafe, putFloatOpaque_name, putFloat_signature, F_R) \ + do_intrinsic(_putDoubleOpaque, jdk_internal_misc_Unsafe, putDoubleOpaque_name, putDouble_signature, F_R) \ + \ + do_name(getReferenceAcquire_name, "getReferenceAcquire") do_name(putReferenceRelease_name, "putReferenceRelease") \ + do_name(getBooleanAcquire_name, "getBooleanAcquire") do_name(putBooleanRelease_name, "putBooleanRelease") \ + do_name(getByteAcquire_name, "getByteAcquire") do_name(putByteRelease_name, "putByteRelease") \ + do_name(getShortAcquire_name, "getShortAcquire") do_name(putShortRelease_name, "putShortRelease") \ + do_name(getCharAcquire_name, "getCharAcquire") do_name(putCharRelease_name, "putCharRelease") \ + do_name(getIntAcquire_name, "getIntAcquire") do_name(putIntRelease_name, "putIntRelease") \ + do_name(getLongAcquire_name, "getLongAcquire") do_name(putLongRelease_name, "putLongRelease") \ + do_name(getFloatAcquire_name, "getFloatAcquire") do_name(putFloatRelease_name, "putFloatRelease") \ + do_name(getDoubleAcquire_name, "getDoubleAcquire") do_name(putDoubleRelease_name, "putDoubleRelease") \ + \ + do_intrinsic(_getReferenceAcquire, jdk_internal_misc_Unsafe, getReferenceAcquire_name, getReference_signature, F_R) \ + do_intrinsic(_getBooleanAcquire, jdk_internal_misc_Unsafe, getBooleanAcquire_name, getBoolean_signature, F_R) \ + do_intrinsic(_getByteAcquire, jdk_internal_misc_Unsafe, getByteAcquire_name, getByte_signature, F_R) \ + do_intrinsic(_getShortAcquire, jdk_internal_misc_Unsafe, getShortAcquire_name, getShort_signature, F_R) \ + do_intrinsic(_getCharAcquire, jdk_internal_misc_Unsafe, getCharAcquire_name, getChar_signature, F_R) \ + do_intrinsic(_getIntAcquire, jdk_internal_misc_Unsafe, getIntAcquire_name, getInt_signature, F_R) \ + do_intrinsic(_getLongAcquire, jdk_internal_misc_Unsafe, getLongAcquire_name, getLong_signature, F_R) \ + do_intrinsic(_getFloatAcquire, jdk_internal_misc_Unsafe, getFloatAcquire_name, getFloat_signature, F_R) \ + do_intrinsic(_getDoubleAcquire, jdk_internal_misc_Unsafe, getDoubleAcquire_name, getDouble_signature, F_R) \ + do_intrinsic(_putReferenceRelease, jdk_internal_misc_Unsafe, putReferenceRelease_name, putReference_signature, F_R) \ + do_intrinsic(_putBooleanRelease, jdk_internal_misc_Unsafe, putBooleanRelease_name, putBoolean_signature, F_R) \ + do_intrinsic(_putByteRelease, jdk_internal_misc_Unsafe, putByteRelease_name, putByte_signature, F_R) \ + do_intrinsic(_putShortRelease, jdk_internal_misc_Unsafe, putShortRelease_name, putShort_signature, F_R) \ + do_intrinsic(_putCharRelease, jdk_internal_misc_Unsafe, putCharRelease_name, putChar_signature, F_R) \ + do_intrinsic(_putIntRelease, jdk_internal_misc_Unsafe, putIntRelease_name, putInt_signature, F_R) \ + do_intrinsic(_putLongRelease, jdk_internal_misc_Unsafe, putLongRelease_name, putLong_signature, F_R) \ + do_intrinsic(_putFloatRelease, jdk_internal_misc_Unsafe, putFloatRelease_name, putFloat_signature, F_R) \ + do_intrinsic(_putDoubleRelease, jdk_internal_misc_Unsafe, putDoubleRelease_name, putDouble_signature, F_R) \ + \ + do_name(getShortUnaligned_name,"getShortUnaligned") do_name(putShortUnaligned_name,"putShortUnaligned") \ + do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \ + do_name(getIntUnaligned_name,"getIntUnaligned") do_name(putIntUnaligned_name,"putIntUnaligned") \ + do_name(getLongUnaligned_name,"getLongUnaligned") do_name(putLongUnaligned_name,"putLongUnaligned") \ + \ + do_intrinsic(_getShortUnaligned, jdk_internal_misc_Unsafe, getShortUnaligned_name, getShort_signature, F_R) \ + do_intrinsic(_getCharUnaligned, jdk_internal_misc_Unsafe, getCharUnaligned_name, getChar_signature, F_R) \ + do_intrinsic(_getIntUnaligned, jdk_internal_misc_Unsafe, getIntUnaligned_name, getInt_signature, F_R) \ + do_intrinsic(_getLongUnaligned, jdk_internal_misc_Unsafe, getLongUnaligned_name, getLong_signature, F_R) \ + do_intrinsic(_putShortUnaligned, jdk_internal_misc_Unsafe, putShortUnaligned_name, putShort_signature, F_R) \ + do_intrinsic(_putCharUnaligned, jdk_internal_misc_Unsafe, putCharUnaligned_name, putChar_signature, F_R) \ + do_intrinsic(_putIntUnaligned, jdk_internal_misc_Unsafe, putIntUnaligned_name, putInt_signature, F_R) \ + do_intrinsic(_putLongUnaligned, jdk_internal_misc_Unsafe, putLongUnaligned_name, putLong_signature, F_R) \ + \ + do_signature(compareAndSetReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ + do_signature(compareAndExchangeReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \ + do_signature(compareAndSetLong_signature, "(Ljava/lang/Object;JJJ)Z") \ + do_signature(compareAndExchangeLong_signature, "(Ljava/lang/Object;JJJ)J") \ + do_signature(compareAndSetInt_signature, "(Ljava/lang/Object;JII)Z") \ + do_signature(compareAndExchangeInt_signature, "(Ljava/lang/Object;JII)I") \ + do_signature(compareAndSetByte_signature, "(Ljava/lang/Object;JBB)Z") \ + do_signature(compareAndExchangeByte_signature, "(Ljava/lang/Object;JBB)B") \ + do_signature(compareAndSetShort_signature, "(Ljava/lang/Object;JSS)Z") \ + do_signature(compareAndExchangeShort_signature, "(Ljava/lang/Object;JSS)S") \ + \ + do_name(compareAndSetReference_name, "compareAndSetReference") \ + do_name(compareAndExchangeReference_name, "compareAndExchangeReference") \ + do_name(compareAndExchangeReferenceAcquire_name, "compareAndExchangeReferenceAcquire") \ + do_name(compareAndExchangeReferenceRelease_name, "compareAndExchangeReferenceRelease") \ + do_name(compareAndSetLong_name, "compareAndSetLong") \ + do_name(compareAndExchangeLong_name, "compareAndExchangeLong") \ + do_name(compareAndExchangeLongAcquire_name, "compareAndExchangeLongAcquire") \ + do_name(compareAndExchangeLongRelease_name, "compareAndExchangeLongRelease") \ + do_name(compareAndSetInt_name, "compareAndSetInt") \ + do_name(compareAndExchangeInt_name, "compareAndExchangeInt") \ + do_name(compareAndExchangeIntAcquire_name, "compareAndExchangeIntAcquire") \ + do_name(compareAndExchangeIntRelease_name, "compareAndExchangeIntRelease") \ + do_name(compareAndSetByte_name, "compareAndSetByte") \ + do_name(compareAndExchangeByte_name, "compareAndExchangeByte") \ + do_name(compareAndExchangeByteAcquire_name, "compareAndExchangeByteAcquire") \ + do_name(compareAndExchangeByteRelease_name, "compareAndExchangeByteRelease") \ + do_name(compareAndSetShort_name, "compareAndSetShort") \ + do_name(compareAndExchangeShort_name, "compareAndExchangeShort") \ + do_name(compareAndExchangeShortAcquire_name, "compareAndExchangeShortAcquire") \ + do_name(compareAndExchangeShortRelease_name, "compareAndExchangeShortRelease") \ + \ + do_name(weakCompareAndSetReferencePlain_name, "weakCompareAndSetReferencePlain") \ + do_name(weakCompareAndSetReferenceAcquire_name, "weakCompareAndSetReferenceAcquire") \ + do_name(weakCompareAndSetReferenceRelease_name, "weakCompareAndSetReferenceRelease") \ + do_name(weakCompareAndSetReference_name, "weakCompareAndSetReference") \ + do_name(weakCompareAndSetLongPlain_name, "weakCompareAndSetLongPlain") \ + do_name(weakCompareAndSetLongAcquire_name, "weakCompareAndSetLongAcquire") \ + do_name(weakCompareAndSetLongRelease_name, "weakCompareAndSetLongRelease") \ + do_name(weakCompareAndSetLong_name, "weakCompareAndSetLong") \ + do_name(weakCompareAndSetIntPlain_name, "weakCompareAndSetIntPlain") \ + do_name(weakCompareAndSetIntAcquire_name, "weakCompareAndSetIntAcquire") \ + do_name(weakCompareAndSetIntRelease_name, "weakCompareAndSetIntRelease") \ + do_name(weakCompareAndSetInt_name, "weakCompareAndSetInt") \ + do_name(weakCompareAndSetBytePlain_name, "weakCompareAndSetBytePlain") \ + do_name(weakCompareAndSetByteAcquire_name, "weakCompareAndSetByteAcquire") \ + do_name(weakCompareAndSetByteRelease_name, "weakCompareAndSetByteRelease") \ + do_name(weakCompareAndSetByte_name, "weakCompareAndSetByte") \ + do_name(weakCompareAndSetShortPlain_name, "weakCompareAndSetShortPlain") \ + do_name(weakCompareAndSetShortAcquire_name, "weakCompareAndSetShortAcquire") \ + do_name(weakCompareAndSetShortRelease_name, "weakCompareAndSetShortRelease") \ + do_name(weakCompareAndSetShort_name, "weakCompareAndSetShort") \ + \ + do_intrinsic(_compareAndSetReference, jdk_internal_misc_Unsafe, compareAndSetReference_name, compareAndSetReference_signature, F_RN) \ + do_intrinsic(_compareAndExchangeReference, jdk_internal_misc_Unsafe, compareAndExchangeReference_name, compareAndExchangeReference_signature, F_RN) \ + do_intrinsic(_compareAndExchangeReferenceAcquire, jdk_internal_misc_Unsafe, compareAndExchangeReferenceAcquire_name, compareAndExchangeReference_signature, F_R) \ + do_intrinsic(_compareAndExchangeReferenceRelease, jdk_internal_misc_Unsafe, compareAndExchangeReferenceRelease_name, compareAndExchangeReference_signature, F_R) \ + do_intrinsic(_compareAndSetLong, jdk_internal_misc_Unsafe, compareAndSetLong_name, compareAndSetLong_signature, F_RN) \ + do_intrinsic(_compareAndExchangeLong, jdk_internal_misc_Unsafe, compareAndExchangeLong_name, compareAndExchangeLong_signature, F_RN) \ + do_intrinsic(_compareAndExchangeLongAcquire, jdk_internal_misc_Unsafe, compareAndExchangeLongAcquire_name, compareAndExchangeLong_signature, F_R) \ + do_intrinsic(_compareAndExchangeLongRelease, jdk_internal_misc_Unsafe, compareAndExchangeLongRelease_name, compareAndExchangeLong_signature, F_R) \ + do_intrinsic(_compareAndSetInt, jdk_internal_misc_Unsafe, compareAndSetInt_name, compareAndSetInt_signature, F_RN) \ + do_intrinsic(_compareAndExchangeInt, jdk_internal_misc_Unsafe, compareAndExchangeInt_name, compareAndExchangeInt_signature, F_RN) \ + do_intrinsic(_compareAndExchangeIntAcquire, jdk_internal_misc_Unsafe, compareAndExchangeIntAcquire_name, compareAndExchangeInt_signature, F_R) \ + do_intrinsic(_compareAndExchangeIntRelease, jdk_internal_misc_Unsafe, compareAndExchangeIntRelease_name, compareAndExchangeInt_signature, F_R) \ + do_intrinsic(_compareAndSetByte, jdk_internal_misc_Unsafe, compareAndSetByte_name, compareAndSetByte_signature, F_R) \ + do_intrinsic(_compareAndExchangeByte, jdk_internal_misc_Unsafe, compareAndExchangeByte_name, compareAndExchangeByte_signature, F_R) \ + do_intrinsic(_compareAndExchangeByteAcquire, jdk_internal_misc_Unsafe, compareAndExchangeByteAcquire_name, compareAndExchangeByte_signature, F_R) \ + do_intrinsic(_compareAndExchangeByteRelease, jdk_internal_misc_Unsafe, compareAndExchangeByteRelease_name, compareAndExchangeByte_signature, F_R) \ + do_intrinsic(_compareAndSetShort, jdk_internal_misc_Unsafe, compareAndSetShort_name, compareAndSetShort_signature, F_R) \ + do_intrinsic(_compareAndExchangeShort, jdk_internal_misc_Unsafe, compareAndExchangeShort_name, compareAndExchangeShort_signature, F_R) \ + do_intrinsic(_compareAndExchangeShortAcquire, jdk_internal_misc_Unsafe, compareAndExchangeShortAcquire_name, compareAndExchangeShort_signature, F_R) \ + do_intrinsic(_compareAndExchangeShortRelease, jdk_internal_misc_Unsafe, compareAndExchangeShortRelease_name, compareAndExchangeShort_signature, F_R) \ + \ + do_intrinsic(_weakCompareAndSetReferencePlain, jdk_internal_misc_Unsafe, weakCompareAndSetReferencePlain_name, compareAndSetReference_signature, F_R) \ + do_intrinsic(_weakCompareAndSetReferenceAcquire,jdk_internal_misc_Unsafe, weakCompareAndSetReferenceAcquire_name, compareAndSetReference_signature, F_R) \ + do_intrinsic(_weakCompareAndSetReferenceRelease,jdk_internal_misc_Unsafe, weakCompareAndSetReferenceRelease_name, compareAndSetReference_signature, F_R) \ + do_intrinsic(_weakCompareAndSetReference, jdk_internal_misc_Unsafe, weakCompareAndSetReference_name, compareAndSetReference_signature, F_R) \ + do_intrinsic(_weakCompareAndSetLongPlain, jdk_internal_misc_Unsafe, weakCompareAndSetLongPlain_name, compareAndSetLong_signature, F_R) \ + do_intrinsic(_weakCompareAndSetLongAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetLongAcquire_name, compareAndSetLong_signature, F_R) \ + do_intrinsic(_weakCompareAndSetLongRelease, jdk_internal_misc_Unsafe, weakCompareAndSetLongRelease_name, compareAndSetLong_signature, F_R) \ + do_intrinsic(_weakCompareAndSetLong, jdk_internal_misc_Unsafe, weakCompareAndSetLong_name, compareAndSetLong_signature, F_R) \ + do_intrinsic(_weakCompareAndSetIntPlain, jdk_internal_misc_Unsafe, weakCompareAndSetIntPlain_name, compareAndSetInt_signature, F_R) \ + do_intrinsic(_weakCompareAndSetIntAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetIntAcquire_name, compareAndSetInt_signature, F_R) \ + do_intrinsic(_weakCompareAndSetIntRelease, jdk_internal_misc_Unsafe, weakCompareAndSetIntRelease_name, compareAndSetInt_signature, F_R) \ + do_intrinsic(_weakCompareAndSetInt, jdk_internal_misc_Unsafe, weakCompareAndSetInt_name, compareAndSetInt_signature, F_R) \ + do_intrinsic(_weakCompareAndSetBytePlain, jdk_internal_misc_Unsafe, weakCompareAndSetBytePlain_name, compareAndSetByte_signature, F_R) \ + do_intrinsic(_weakCompareAndSetByteAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetByteAcquire_name, compareAndSetByte_signature, F_R) \ + do_intrinsic(_weakCompareAndSetByteRelease, jdk_internal_misc_Unsafe, weakCompareAndSetByteRelease_name, compareAndSetByte_signature, F_R) \ + do_intrinsic(_weakCompareAndSetByte, jdk_internal_misc_Unsafe, weakCompareAndSetByte_name, compareAndSetByte_signature, F_R) \ + do_intrinsic(_weakCompareAndSetShortPlain, jdk_internal_misc_Unsafe, weakCompareAndSetShortPlain_name, compareAndSetShort_signature, F_R) \ + do_intrinsic(_weakCompareAndSetShortAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetShortAcquire_name, compareAndSetShort_signature, F_R) \ + do_intrinsic(_weakCompareAndSetShortRelease, jdk_internal_misc_Unsafe, weakCompareAndSetShortRelease_name, compareAndSetShort_signature, F_R) \ + do_intrinsic(_weakCompareAndSetShort, jdk_internal_misc_Unsafe, weakCompareAndSetShort_name, compareAndSetShort_signature, F_R) \ + \ + do_intrinsic(_getAndAddInt, jdk_internal_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \ + do_name( getAndAddInt_name, "getAndAddInt") \ + do_signature(getAndAddInt_signature, "(Ljava/lang/Object;JI)I" ) \ + do_intrinsic(_getAndAddLong, jdk_internal_misc_Unsafe, getAndAddLong_name, getAndAddLong_signature, F_R) \ + do_name( getAndAddLong_name, "getAndAddLong") \ + do_signature(getAndAddLong_signature, "(Ljava/lang/Object;JJ)J" ) \ + do_intrinsic(_getAndAddByte, jdk_internal_misc_Unsafe, getAndAddByte_name, getAndAddByte_signature, F_R) \ + do_name( getAndAddByte_name, "getAndAddByte") \ + do_signature(getAndAddByte_signature, "(Ljava/lang/Object;JB)B" ) \ + do_intrinsic(_getAndAddShort, jdk_internal_misc_Unsafe, getAndAddShort_name, getAndAddShort_signature, F_R) \ + do_name( getAndAddShort_name, "getAndAddShort") \ + do_signature(getAndAddShort_signature, "(Ljava/lang/Object;JS)S" ) \ + do_intrinsic(_getAndSetInt, jdk_internal_misc_Unsafe, getAndSetInt_name, getAndSetInt_signature, F_R) \ + do_name( getAndSetInt_name, "getAndSetInt") \ + do_alias( getAndSetInt_signature, /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature) \ + do_intrinsic(_getAndSetLong, jdk_internal_misc_Unsafe, getAndSetLong_name, getAndSetLong_signature, F_R) \ + do_name( getAndSetLong_name, "getAndSetLong") \ + do_alias( getAndSetLong_signature, /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature) \ + do_intrinsic(_getAndSetByte, jdk_internal_misc_Unsafe, getAndSetByte_name, getAndSetByte_signature, F_R) \ + do_name( getAndSetByte_name, "getAndSetByte") \ + do_alias( getAndSetByte_signature, /*"(Ljava/lang/Object;JB)B"*/ getAndAddByte_signature) \ + do_intrinsic(_getAndSetShort, jdk_internal_misc_Unsafe, getAndSetShort_name, getAndSetShort_signature, F_R) \ + do_name( getAndSetShort_name, "getAndSetShort") \ + do_alias( getAndSetShort_signature, /*"(Ljava/lang/Object;JS)S"*/ getAndAddShort_signature) \ + do_intrinsic(_getAndSetReference, jdk_internal_misc_Unsafe, getAndSetReference_name, getAndSetReference_signature, F_R) \ + do_name( getAndSetReference_name, "getAndSetReference") \ + do_signature(getAndSetReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \ + \ + /* (2) Bytecode intrinsics */ \ + \ + do_intrinsic(_park, jdk_internal_misc_Unsafe, park_name, park_signature, F_R) \ + do_name( park_name, "park") \ + do_signature(park_signature, "(ZJ)V") \ + do_intrinsic(_unpark, jdk_internal_misc_Unsafe, unpark_name, unpark_signature, F_R) \ + do_name( unpark_name, "unpark") \ + do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \ + \ + do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \ + do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \ + do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \ + \ + do_intrinsic(_StringBuilder_append_char, java_lang_StringBuilder, append_name, char_StringBuilder_signature, F_R) \ + do_intrinsic(_StringBuilder_append_int, java_lang_StringBuilder, append_name, int_StringBuilder_signature, F_R) \ + do_intrinsic(_StringBuilder_append_String, java_lang_StringBuilder, append_name, String_StringBuilder_signature, F_R) \ + \ + do_intrinsic(_StringBuilder_toString, java_lang_StringBuilder, toString_name, void_string_signature, F_R) \ + \ + do_intrinsic(_StringBuffer_void, java_lang_StringBuffer, object_initializer_name, void_method_signature, F_R) \ + do_intrinsic(_StringBuffer_int, java_lang_StringBuffer, object_initializer_name, int_void_signature, F_R) \ + do_intrinsic(_StringBuffer_String, java_lang_StringBuffer, object_initializer_name, string_void_signature, F_R) \ + \ + do_intrinsic(_StringBuffer_append_char, java_lang_StringBuffer, append_name, char_StringBuffer_signature, F_Y) \ + do_intrinsic(_StringBuffer_append_int, java_lang_StringBuffer, append_name, int_StringBuffer_signature, F_Y) \ + do_intrinsic(_StringBuffer_append_String, java_lang_StringBuffer, append_name, String_StringBuffer_signature, F_Y) \ + \ + do_intrinsic(_StringBuffer_toString, java_lang_StringBuffer, toString_name, void_string_signature, F_Y) \ + \ + do_intrinsic(_Integer_toString, java_lang_Integer, toString_name, int_String_signature, F_S) \ + \ + do_intrinsic(_String_String, java_lang_String, object_initializer_name, string_void_signature, F_R) \ + \ + do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ + /* (symbol object_initializer_name defined above) */ \ + \ + do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_object_array_object_signature, F_R) \ + /* (symbols invoke_name and invoke_signature defined above) */ \ + /* the polymorphic MH intrinsics must be in compact order, with _invokeGeneric first and _linkToInterface last */ \ + do_intrinsic(_invokeGeneric, java_lang_invoke_MethodHandle, invoke_name, star_name, F_RN) \ + do_intrinsic(_invokeBasic, java_lang_invoke_MethodHandle, invokeBasic_name, star_name, F_RN) \ + do_intrinsic(_linkToVirtual, java_lang_invoke_MethodHandle, linkToVirtual_name, star_name, F_SN) \ + do_intrinsic(_linkToStatic, java_lang_invoke_MethodHandle, linkToStatic_name, star_name, F_SN) \ + do_intrinsic(_linkToSpecial, java_lang_invoke_MethodHandle, linkToSpecial_name, star_name, F_SN) \ + do_intrinsic(_linkToInterface, java_lang_invoke_MethodHandle, linkToInterface_name, star_name, F_SN) \ + /* special marker for bytecode generated for the JVM from a LambdaForm: */ \ + do_intrinsic(_compiledLambdaForm, java_lang_invoke_MethodHandle, compiledLambdaForm_name, star_name, F_RN) \ + \ + /* unboxing methods: */ \ + do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ + do_name( booleanValue_name, "booleanValue") \ + do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \ + do_name( byteValue_name, "byteValue") \ + do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \ + do_name( charValue_name, "charValue") \ + do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \ + do_name( shortValue_name, "shortValue") \ + do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \ + do_name( intValue_name, "intValue") \ + do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \ + do_name( longValue_name, "longValue") \ + do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \ + do_name( floatValue_name, "floatValue") \ + do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \ + do_name( doubleValue_name, "doubleValue") \ + \ + /* boxing methods: */ \ + do_name( valueOf_name, "valueOf") \ + do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \ + do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \ + do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \ + do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \ + do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \ + do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \ + do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \ + do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \ + do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \ + do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \ + do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \ + do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \ + do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \ + do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \ + do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \ + do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \ + \ + /* forEachRemaining */ \ + do_intrinsic(_forEachRemaining, java_util_stream_StreamsRangeIntSpliterator, forEachRemaining_name, forEachRemaining_signature, F_R) \ + do_name( forEachRemaining_name, "forEachRemaining") \ + do_name( forEachRemaining_signature, "(Ljava/util/function/IntConsumer;)V") \ + + /*end*/ + +#endif // SHARE_CLASSFILE_VMINTRINSICS_HPP diff --git a/src/hotspot/share/classfile/vmSymbols.cpp b/src/hotspot/share/classfile/vmSymbols.cpp index ef6dbdc781c..cb02bc5be3b 100644 --- a/src/hotspot/share/classfile/vmSymbols.cpp +++ b/src/hotspot/share/classfile/vmSymbols.cpp @@ -293,822 +293,3 @@ vmSymbols::SID vmSymbols::find_sid(const char* symbol_name) { if (symbol == NULL) return NO_SID; return find_sid(symbol); } - -static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) { -#define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0)) - switch (TYPE2(type, unboxing)) { -#define BASIC_TYPE_CASE(type, box, unbox) \ - case TYPE2(type, false): return vmIntrinsics::box; \ - case TYPE2(type, true): return vmIntrinsics::unbox - BASIC_TYPE_CASE(T_BOOLEAN, _Boolean_valueOf, _booleanValue); - BASIC_TYPE_CASE(T_BYTE, _Byte_valueOf, _byteValue); - BASIC_TYPE_CASE(T_CHAR, _Character_valueOf, _charValue); - BASIC_TYPE_CASE(T_SHORT, _Short_valueOf, _shortValue); - BASIC_TYPE_CASE(T_INT, _Integer_valueOf, _intValue); - BASIC_TYPE_CASE(T_LONG, _Long_valueOf, _longValue); - BASIC_TYPE_CASE(T_FLOAT, _Float_valueOf, _floatValue); - BASIC_TYPE_CASE(T_DOUBLE, _Double_valueOf, _doubleValue); -#undef BASIC_TYPE_CASE - } -#undef TYPE2 - return vmIntrinsics::_none; -} - -vmIntrinsics::ID vmIntrinsics::for_boxing(BasicType type) { - return wrapper_intrinsic(type, false); -} -vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) { - return wrapper_intrinsic(type, true); -} - -vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) { -#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d)) - switch (SRC_DEST(src, dest)) { - case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat; - case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits; - - case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble; - case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits; - } -#undef SRC_DEST - - return vmIntrinsics::_none; -} - -bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - switch(id) { -#ifdef JFR_HAVE_INTRINSICS - case vmIntrinsics::_counterTime: -#endif - case vmIntrinsics::_currentTimeMillis: - case vmIntrinsics::_nanoTime: - case vmIntrinsics::_floatToRawIntBits: - case vmIntrinsics::_intBitsToFloat: - case vmIntrinsics::_doubleToRawLongBits: - case vmIntrinsics::_longBitsToDouble: - case vmIntrinsics::_getClass: - case vmIntrinsics::_isInstance: - case vmIntrinsics::_currentThread: - case vmIntrinsics::_dabs: - case vmIntrinsics::_fabs: - case vmIntrinsics::_iabs: - case vmIntrinsics::_labs: - case vmIntrinsics::_dsqrt: - case vmIntrinsics::_dsin: - case vmIntrinsics::_dcos: - case vmIntrinsics::_dtan: - case vmIntrinsics::_dlog: - case vmIntrinsics::_dlog10: - case vmIntrinsics::_dexp: - case vmIntrinsics::_dpow: - case vmIntrinsics::_checkIndex: - case vmIntrinsics::_Reference_get: - case vmIntrinsics::_updateCRC32: - case vmIntrinsics::_updateBytesCRC32: - case vmIntrinsics::_updateByteBufferCRC32: - case vmIntrinsics::_vectorizedMismatch: - case vmIntrinsics::_fmaD: - case vmIntrinsics::_fmaF: - case vmIntrinsics::_isDigit: - case vmIntrinsics::_isLowerCase: - case vmIntrinsics::_isUpperCase: - case vmIntrinsics::_isWhitespace: - return true; - default: - return false; - } -} - -bool vmIntrinsics::can_trap(vmIntrinsics::ID id) { - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - switch(id) { -#ifdef JFR_HAVE_INTRINSICS - case vmIntrinsics::_counterTime: - case vmIntrinsics::_getClassId: -#endif - case vmIntrinsics::_currentTimeMillis: - case vmIntrinsics::_nanoTime: - case vmIntrinsics::_floatToRawIntBits: - case vmIntrinsics::_intBitsToFloat: - case vmIntrinsics::_doubleToRawLongBits: - case vmIntrinsics::_longBitsToDouble: - case vmIntrinsics::_currentThread: - case vmIntrinsics::_dabs: - case vmIntrinsics::_fabs: - case vmIntrinsics::_iabs: - case vmIntrinsics::_labs: - case vmIntrinsics::_dsqrt: - case vmIntrinsics::_dsin: - case vmIntrinsics::_dcos: - case vmIntrinsics::_dtan: - case vmIntrinsics::_dlog: - case vmIntrinsics::_dlog10: - case vmIntrinsics::_dexp: - case vmIntrinsics::_dpow: - case vmIntrinsics::_updateCRC32: - case vmIntrinsics::_updateBytesCRC32: - case vmIntrinsics::_updateByteBufferCRC32: - case vmIntrinsics::_vectorizedMismatch: - case vmIntrinsics::_fmaD: - case vmIntrinsics::_fmaF: - return false; - default: - return true; - } -} - -// Some intrinsics produce different results if they are not pinned -bool vmIntrinsics::should_be_pinned(vmIntrinsics::ID id) { - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - switch(id) { -#ifdef JFR_HAVE_INTRINSICS - case vmIntrinsics::_counterTime: -#endif - case vmIntrinsics::_currentTimeMillis: - case vmIntrinsics::_nanoTime: - return true; - default: - return false; - } -} - -bool vmIntrinsics::does_virtual_dispatch(vmIntrinsics::ID id) { - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - switch(id) { - case vmIntrinsics::_hashCode: - case vmIntrinsics::_clone: - return true; - break; - default: - return false; - } -} - -int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) { - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - switch (id) { - case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: - case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: - case vmIntrinsics::_electronicCodeBook_encryptAESCrypt: - case vmIntrinsics::_electronicCodeBook_decryptAESCrypt: - case vmIntrinsics::_counterMode_AESCrypt: - return 1; - case vmIntrinsics::_digestBase_implCompressMB: - return 4; - default: - return 0; - } -} - -bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - - // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in - // the following switch statement. - if (!InlineNatives) { - switch (id) { - case vmIntrinsics::_indexOfL: - case vmIntrinsics::_indexOfU: - case vmIntrinsics::_indexOfUL: - case vmIntrinsics::_indexOfIL: - case vmIntrinsics::_indexOfIU: - case vmIntrinsics::_indexOfIUL: - case vmIntrinsics::_indexOfU_char: - case vmIntrinsics::_compareToL: - case vmIntrinsics::_compareToU: - case vmIntrinsics::_compareToLU: - case vmIntrinsics::_compareToUL: - case vmIntrinsics::_equalsL: - case vmIntrinsics::_equalsU: - case vmIntrinsics::_equalsC: - case vmIntrinsics::_getCharStringU: - case vmIntrinsics::_putCharStringU: - case vmIntrinsics::_compressStringC: - case vmIntrinsics::_compressStringB: - case vmIntrinsics::_inflateStringC: - case vmIntrinsics::_inflateStringB: - case vmIntrinsics::_getAndAddInt: - case vmIntrinsics::_getAndAddLong: - case vmIntrinsics::_getAndSetInt: - case vmIntrinsics::_getAndSetLong: - case vmIntrinsics::_getAndSetReference: - case vmIntrinsics::_loadFence: - case vmIntrinsics::_storeFence: - case vmIntrinsics::_fullFence: - case vmIntrinsics::_hasNegatives: - case vmIntrinsics::_Reference_get: - break; - default: - return true; - } - } - - switch (id) { - case vmIntrinsics::_isInstance: - case vmIntrinsics::_isAssignableFrom: - case vmIntrinsics::_getModifiers: - case vmIntrinsics::_isInterface: - case vmIntrinsics::_isArray: - case vmIntrinsics::_isPrimitive: - case vmIntrinsics::_isHidden: - case vmIntrinsics::_getSuperclass: - case vmIntrinsics::_Class_cast: - case vmIntrinsics::_getLength: - case vmIntrinsics::_newArray: - case vmIntrinsics::_getClass: - if (!InlineClassNatives) return true; - break; - case vmIntrinsics::_currentThread: - if (!InlineThreadNatives) return true; - break; - case vmIntrinsics::_floatToRawIntBits: - case vmIntrinsics::_intBitsToFloat: - case vmIntrinsics::_doubleToRawLongBits: - case vmIntrinsics::_longBitsToDouble: - case vmIntrinsics::_ceil: - case vmIntrinsics::_floor: - case vmIntrinsics::_rint: - case vmIntrinsics::_dabs: - case vmIntrinsics::_fabs: - case vmIntrinsics::_iabs: - case vmIntrinsics::_labs: - case vmIntrinsics::_dsqrt: - case vmIntrinsics::_dsin: - case vmIntrinsics::_dcos: - case vmIntrinsics::_dtan: - case vmIntrinsics::_dlog: - case vmIntrinsics::_dexp: - case vmIntrinsics::_dpow: - case vmIntrinsics::_dlog10: - case vmIntrinsics::_datan2: - case vmIntrinsics::_min: - case vmIntrinsics::_max: - case vmIntrinsics::_floatToIntBits: - case vmIntrinsics::_doubleToLongBits: - case vmIntrinsics::_maxF: - case vmIntrinsics::_minF: - case vmIntrinsics::_maxD: - case vmIntrinsics::_minD: - if (!InlineMathNatives) return true; - break; - case vmIntrinsics::_fmaD: - case vmIntrinsics::_fmaF: - if (!InlineMathNatives || !UseFMA) return true; - break; - case vmIntrinsics::_arraycopy: - if (!InlineArrayCopy) return true; - break; - case vmIntrinsics::_updateCRC32: - case vmIntrinsics::_updateBytesCRC32: - case vmIntrinsics::_updateByteBufferCRC32: - if (!UseCRC32Intrinsics) return true; - break; - case vmIntrinsics::_getReference: - case vmIntrinsics::_getBoolean: - case vmIntrinsics::_getByte: - case vmIntrinsics::_getShort: - case vmIntrinsics::_getChar: - case vmIntrinsics::_getInt: - case vmIntrinsics::_getLong: - case vmIntrinsics::_getFloat: - case vmIntrinsics::_getDouble: - case vmIntrinsics::_putReference: - case vmIntrinsics::_putBoolean: - case vmIntrinsics::_putByte: - case vmIntrinsics::_putShort: - case vmIntrinsics::_putChar: - case vmIntrinsics::_putInt: - case vmIntrinsics::_putLong: - case vmIntrinsics::_putFloat: - case vmIntrinsics::_putDouble: - case vmIntrinsics::_getReferenceVolatile: - case vmIntrinsics::_getBooleanVolatile: - case vmIntrinsics::_getByteVolatile: - case vmIntrinsics::_getShortVolatile: - case vmIntrinsics::_getCharVolatile: - case vmIntrinsics::_getIntVolatile: - case vmIntrinsics::_getLongVolatile: - case vmIntrinsics::_getFloatVolatile: - case vmIntrinsics::_getDoubleVolatile: - case vmIntrinsics::_putReferenceVolatile: - case vmIntrinsics::_putBooleanVolatile: - case vmIntrinsics::_putByteVolatile: - case vmIntrinsics::_putShortVolatile: - case vmIntrinsics::_putCharVolatile: - case vmIntrinsics::_putIntVolatile: - case vmIntrinsics::_putLongVolatile: - case vmIntrinsics::_putFloatVolatile: - case vmIntrinsics::_putDoubleVolatile: - case vmIntrinsics::_getReferenceAcquire: - case vmIntrinsics::_getBooleanAcquire: - case vmIntrinsics::_getByteAcquire: - case vmIntrinsics::_getShortAcquire: - case vmIntrinsics::_getCharAcquire: - case vmIntrinsics::_getIntAcquire: - case vmIntrinsics::_getLongAcquire: - case vmIntrinsics::_getFloatAcquire: - case vmIntrinsics::_getDoubleAcquire: - case vmIntrinsics::_putReferenceRelease: - case vmIntrinsics::_putBooleanRelease: - case vmIntrinsics::_putByteRelease: - case vmIntrinsics::_putShortRelease: - case vmIntrinsics::_putCharRelease: - case vmIntrinsics::_putIntRelease: - case vmIntrinsics::_putLongRelease: - case vmIntrinsics::_putFloatRelease: - case vmIntrinsics::_putDoubleRelease: - case vmIntrinsics::_getReferenceOpaque: - case vmIntrinsics::_getBooleanOpaque: - case vmIntrinsics::_getByteOpaque: - case vmIntrinsics::_getShortOpaque: - case vmIntrinsics::_getCharOpaque: - case vmIntrinsics::_getIntOpaque: - case vmIntrinsics::_getLongOpaque: - case vmIntrinsics::_getFloatOpaque: - case vmIntrinsics::_getDoubleOpaque: - case vmIntrinsics::_putReferenceOpaque: - case vmIntrinsics::_putBooleanOpaque: - case vmIntrinsics::_putByteOpaque: - case vmIntrinsics::_putShortOpaque: - case vmIntrinsics::_putCharOpaque: - case vmIntrinsics::_putIntOpaque: - case vmIntrinsics::_putLongOpaque: - case vmIntrinsics::_putFloatOpaque: - case vmIntrinsics::_putDoubleOpaque: - case vmIntrinsics::_getAndAddInt: - case vmIntrinsics::_getAndAddLong: - case vmIntrinsics::_getAndSetInt: - case vmIntrinsics::_getAndSetLong: - case vmIntrinsics::_getAndSetReference: - case vmIntrinsics::_loadFence: - case vmIntrinsics::_storeFence: - case vmIntrinsics::_fullFence: - case vmIntrinsics::_compareAndSetLong: - case vmIntrinsics::_weakCompareAndSetLong: - case vmIntrinsics::_weakCompareAndSetLongPlain: - case vmIntrinsics::_weakCompareAndSetLongAcquire: - case vmIntrinsics::_weakCompareAndSetLongRelease: - case vmIntrinsics::_compareAndSetInt: - case vmIntrinsics::_weakCompareAndSetInt: - case vmIntrinsics::_weakCompareAndSetIntPlain: - case vmIntrinsics::_weakCompareAndSetIntAcquire: - case vmIntrinsics::_weakCompareAndSetIntRelease: - case vmIntrinsics::_compareAndSetReference: - case vmIntrinsics::_weakCompareAndSetReference: - case vmIntrinsics::_weakCompareAndSetReferencePlain: - case vmIntrinsics::_weakCompareAndSetReferenceAcquire: - case vmIntrinsics::_weakCompareAndSetReferenceRelease: - case vmIntrinsics::_compareAndExchangeInt: - case vmIntrinsics::_compareAndExchangeIntAcquire: - case vmIntrinsics::_compareAndExchangeIntRelease: - case vmIntrinsics::_compareAndExchangeLong: - case vmIntrinsics::_compareAndExchangeLongAcquire: - case vmIntrinsics::_compareAndExchangeLongRelease: - case vmIntrinsics::_compareAndExchangeReference: - case vmIntrinsics::_compareAndExchangeReferenceAcquire: - case vmIntrinsics::_compareAndExchangeReferenceRelease: - if (!InlineUnsafeOps) return true; - break; - case vmIntrinsics::_getShortUnaligned: - case vmIntrinsics::_getCharUnaligned: - case vmIntrinsics::_getIntUnaligned: - case vmIntrinsics::_getLongUnaligned: - case vmIntrinsics::_putShortUnaligned: - case vmIntrinsics::_putCharUnaligned: - case vmIntrinsics::_putIntUnaligned: - case vmIntrinsics::_putLongUnaligned: - case vmIntrinsics::_allocateInstance: - if (!InlineUnsafeOps || !UseUnalignedAccesses) return true; - break; - case vmIntrinsics::_hashCode: - if (!InlineObjectHash) return true; - break; - case vmIntrinsics::_aescrypt_encryptBlock: - case vmIntrinsics::_aescrypt_decryptBlock: - if (!UseAESIntrinsics) return true; - break; - case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: - case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: - if (!UseAESIntrinsics) return true; - break; - case vmIntrinsics::_electronicCodeBook_encryptAESCrypt: - case vmIntrinsics::_electronicCodeBook_decryptAESCrypt: - if (!UseAESIntrinsics) return true; - break; - case vmIntrinsics::_counterMode_AESCrypt: - if (!UseAESCTRIntrinsics) return true; - break; - case vmIntrinsics::_md5_implCompress: - if (!UseMD5Intrinsics) return true; - break; - case vmIntrinsics::_sha_implCompress: - if (!UseSHA1Intrinsics) return true; - break; - case vmIntrinsics::_sha2_implCompress: - if (!UseSHA256Intrinsics) return true; - break; - case vmIntrinsics::_sha5_implCompress: - if (!UseSHA512Intrinsics) return true; - break; - case vmIntrinsics::_digestBase_implCompressMB: - if (!(UseMD5Intrinsics || UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return true; - break; - case vmIntrinsics::_ghash_processBlocks: - if (!UseGHASHIntrinsics) return true; - break; - case vmIntrinsics::_base64_encodeBlock: - if (!UseBASE64Intrinsics) return true; - break; - case vmIntrinsics::_updateBytesCRC32C: - case vmIntrinsics::_updateDirectByteBufferCRC32C: - if (!UseCRC32CIntrinsics) return true; - break; - case vmIntrinsics::_vectorizedMismatch: - if (!UseVectorizedMismatchIntrinsic) return true; - break; - case vmIntrinsics::_updateBytesAdler32: - case vmIntrinsics::_updateByteBufferAdler32: - if (!UseAdler32Intrinsics) return true; - break; - case vmIntrinsics::_copyMemory: - if (!InlineArrayCopy || !InlineUnsafeOps) return true; - break; -#ifdef COMPILER1 - case vmIntrinsics::_checkIndex: - if (!InlineNIOCheckIndex) return true; - break; -#endif // COMPILER1 -#ifdef COMPILER2 - case vmIntrinsics::_clone: - case vmIntrinsics::_copyOf: - case vmIntrinsics::_copyOfRange: - // These intrinsics use both the objectcopy and the arraycopy - // intrinsic mechanism. - if (!InlineObjectCopy || !InlineArrayCopy) return true; - break; - case vmIntrinsics::_compareToL: - case vmIntrinsics::_compareToU: - case vmIntrinsics::_compareToLU: - case vmIntrinsics::_compareToUL: - if (!SpecialStringCompareTo) return true; - break; - case vmIntrinsics::_indexOfL: - case vmIntrinsics::_indexOfU: - case vmIntrinsics::_indexOfUL: - case vmIntrinsics::_indexOfIL: - case vmIntrinsics::_indexOfIU: - case vmIntrinsics::_indexOfIUL: - case vmIntrinsics::_indexOfU_char: - if (!SpecialStringIndexOf) return true; - break; - case vmIntrinsics::_equalsL: - case vmIntrinsics::_equalsU: - if (!SpecialStringEquals) return true; - break; - case vmIntrinsics::_equalsB: - case vmIntrinsics::_equalsC: - if (!SpecialArraysEquals) return true; - break; - case vmIntrinsics::_encodeISOArray: - case vmIntrinsics::_encodeByteISOArray: - if (!SpecialEncodeISOArray) return true; - break; - case vmIntrinsics::_getCallerClass: - if (!InlineReflectionGetCallerClass) return true; - break; - case vmIntrinsics::_multiplyToLen: - if (!UseMultiplyToLenIntrinsic) return true; - break; - case vmIntrinsics::_squareToLen: - if (!UseSquareToLenIntrinsic) return true; - break; - case vmIntrinsics::_mulAdd: - if (!UseMulAddIntrinsic) return true; - break; - case vmIntrinsics::_montgomeryMultiply: - if (!UseMontgomeryMultiplyIntrinsic) return true; - break; - case vmIntrinsics::_montgomerySquare: - if (!UseMontgomerySquareIntrinsic) return true; - break; - case vmIntrinsics::_bigIntegerRightShiftWorker: - case vmIntrinsics::_bigIntegerLeftShiftWorker: - break; - case vmIntrinsics::_addExactI: - case vmIntrinsics::_addExactL: - case vmIntrinsics::_decrementExactI: - case vmIntrinsics::_decrementExactL: - case vmIntrinsics::_incrementExactI: - case vmIntrinsics::_incrementExactL: - case vmIntrinsics::_multiplyExactI: - case vmIntrinsics::_multiplyExactL: - case vmIntrinsics::_negateExactI: - case vmIntrinsics::_negateExactL: - case vmIntrinsics::_subtractExactI: - case vmIntrinsics::_subtractExactL: - if (!UseMathExactIntrinsics || !InlineMathNatives) return true; - break; - case vmIntrinsics::_isDigit: - case vmIntrinsics::_isLowerCase: - case vmIntrinsics::_isUpperCase: - case vmIntrinsics::_isWhitespace: - if (!UseCharacterCompareIntrinsics) return true; - break; - case vmIntrinsics::_dcopySign: - case vmIntrinsics::_fcopySign: - if (!InlineMathNatives || !UseCopySignIntrinsic) return true; - break; - case vmIntrinsics::_dsignum: - case vmIntrinsics::_fsignum: - if (!InlineMathNatives || !UseSignumIntrinsic) return true; - break; -#endif // COMPILER2 - default: - return false; - } - - return false; -} - -#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" -static const char* vm_intrinsic_name_bodies = - VM_INTRINSICS_DO(VM_INTRINSIC_INITIALIZE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - -static const char* vm_intrinsic_name_table[vmIntrinsics::ID_LIMIT]; -static TriBoolArray<vmIntrinsics::ID_LIMIT, int> vm_intrinsic_control_words; - -static void init_vm_intrinsic_name_table() { - const char** nt = &vm_intrinsic_name_table[0]; - char* string = (char*) &vm_intrinsic_name_bodies[0]; - for (int index = vmIntrinsics::FIRST_ID; index < vmIntrinsics::ID_LIMIT; index++) { - nt[index] = string; - string += strlen(string); // skip string body - string += 1; // skip trailing null - } - assert(!strcmp(nt[vmIntrinsics::_hashCode], "_hashCode"), "lined up"); - nt[vmIntrinsics::_none] = "_none"; -} - -const char* vmIntrinsics::name_at(vmIntrinsics::ID id) { - const char** nt = &vm_intrinsic_name_table[0]; - if (nt[_none] == NULL) { - init_vm_intrinsic_name_table(); - } - - if ((uint)id < (uint)ID_LIMIT) - return vm_intrinsic_name_table[(uint)id]; - else - return "(unknown intrinsic)"; -} - -vmIntrinsics::ID vmIntrinsics::find_id(const char* name) { - const char** nt = &vm_intrinsic_name_table[0]; - if (nt[_none] == NULL) { - init_vm_intrinsic_name_table(); - } - - for (int index = FIRST_ID; index < ID_LIMIT; ++index) { - if (0 == strcmp(name, nt[index])) { - return ID_from(index); - } - } - - return _none; -} - -bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) { - vmIntrinsics::ID id = method->intrinsic_id(); - return is_disabled_by_flags(id); -} - -bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) { - assert(id > _none && id < ID_LIMIT, "must be a VM intrinsic"); - - // not initialized yet, process Control/DisableIntrinsic - if (vm_intrinsic_control_words[_none].is_default()) { - for (ControlIntrinsicIter iter(ControlIntrinsic); *iter != NULL; ++iter) { - vmIntrinsics::ID id = vmIntrinsics::find_id(*iter); - - if (id != vmIntrinsics::_none) { - vm_intrinsic_control_words[id] = iter.is_enabled() && !disabled_by_jvm_flags(id); - } - } - - // Order matters, DisableIntrinsic can overwrite ControlIntrinsic - for (ControlIntrinsicIter iter(DisableIntrinsic, true/*disable_all*/); *iter != NULL; ++iter) { - vmIntrinsics::ID id = vmIntrinsics::find_id(*iter); - - if (id != vmIntrinsics::_none) { - vm_intrinsic_control_words[id] = false; - } - } - - vm_intrinsic_control_words[_none] = true; - } - - TriBool b = vm_intrinsic_control_words[id]; - if (b.is_default()) { - // unknown yet, query and cache it - b = vm_intrinsic_control_words[id] = !disabled_by_jvm_flags(id); - } - - return !b; -} - -// These are flag-matching functions: -inline bool match_F_R(jshort flags) { - const int req = 0; - const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; - return (flags & (req | neg)) == req; -} -inline bool match_F_Y(jshort flags) { - const int req = JVM_ACC_SYNCHRONIZED; - const int neg = JVM_ACC_STATIC; - return (flags & (req | neg)) == req; -} -inline bool match_F_RN(jshort flags) { - const int req = JVM_ACC_NATIVE; - const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; - return (flags & (req | neg)) == req; -} -inline bool match_F_S(jshort flags) { - const int req = JVM_ACC_STATIC; - const int neg = JVM_ACC_SYNCHRONIZED; - return (flags & (req | neg)) == req; -} -inline bool match_F_SN(jshort flags) { - const int req = JVM_ACC_STATIC | JVM_ACC_NATIVE; - const int neg = JVM_ACC_SYNCHRONIZED; - return (flags & (req | neg)) == req; -} -inline bool match_F_RNY(jshort flags) { - const int req = JVM_ACC_NATIVE | JVM_ACC_SYNCHRONIZED; - const int neg = JVM_ACC_STATIC; - return (flags & (req | neg)) == req; -} - -// These are for forming case labels: -#define ID3(x, y, z) (( jlong)(z) + \ - ((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \ - ((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) -#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) - -vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder, - vmSymbols::SID name, - vmSymbols::SID sig, - jshort flags) { - assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit"); - - // Let the C compiler build the decision tree. - -#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ - case ID3(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig)): \ - if (!match_##fcode(flags)) break; \ - return id; - - switch (ID3(holder, name, sig)) { - VM_INTRINSICS_DO(VM_INTRINSIC_CASE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - } - return vmIntrinsics::_none; - -#undef VM_INTRINSIC_CASE -} - - -const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf, int buflen) { - const char* str = name_at(id); -#ifndef PRODUCT - const char* kname = vmSymbols::name_for(class_for(id)); - const char* mname = vmSymbols::name_for(name_for(id)); - const char* sname = vmSymbols::name_for(signature_for(id)); - const char* fname = ""; - switch (flags_for(id)) { - case F_Y: fname = "synchronized "; break; - case F_RN: fname = "native "; break; - case F_SN: fname = "native static "; break; - case F_S: fname = "static "; break; - case F_RNY:fname = "native synchronized "; break; - default: break; - } - const char* kptr = strrchr(kname, JVM_SIGNATURE_SLASH); - if (kptr != NULL) kname = kptr + 1; - int len = jio_snprintf(buf, buflen, "%s: %s%s.%s%s", - str, fname, kname, mname, sname); - if (len < buflen) - str = buf; -#endif //PRODUCT - return str; -} - - -// These are to get information about intrinsics. - -#define ID4(x, y, z, f) ((ID3(x, y, z) << vmIntrinsics::log2_FLAG_LIMIT) | (jlong) (f)) - -static const jlong intrinsic_info_array[vmIntrinsics::ID_LIMIT+1] = { -#define VM_INTRINSIC_INFO(ignore_id, klass, name, sig, fcode) \ - ID4(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig), vmIntrinsics::fcode), - - 0, VM_INTRINSICS_DO(VM_INTRINSIC_INFO, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) - 0 -#undef VM_INTRINSIC_INFO -}; - -inline jlong intrinsic_info(vmIntrinsics::ID id) { - return intrinsic_info_array[vmIntrinsics::ID_from((int)id)]; -} - -vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) { - jlong info = intrinsic_info(id); - int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); - assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, ""); - return vmSymbols::SID( (info >> shift) & mask ); -} - -vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) { - jlong info = intrinsic_info(id); - int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); - assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, ""); - return vmSymbols::SID( (info >> shift) & mask ); -} - -vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) { - jlong info = intrinsic_info(id); - int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); - assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, ""); - return vmSymbols::SID( (info >> shift) & mask ); -} - -vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) { - jlong info = intrinsic_info(id); - int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT); - assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, ""); - return Flags( (info >> shift) & mask ); -} - - -#ifndef PRODUCT -// verify_method performs an extra check on a matched intrinsic method - -static bool match_method(Method* m, Symbol* n, Symbol* s) { - return (m->name() == n && - m->signature() == s); -} - -static vmIntrinsics::ID match_method_with_klass(Method* m, Symbol* mk) { -#define VM_INTRINSIC_MATCH(id, klassname, namepart, sigpart, flags) \ - { Symbol* k = vmSymbols::klassname(); \ - if (mk == k) { \ - Symbol* n = vmSymbols::namepart(); \ - Symbol* s = vmSymbols::sigpart(); \ - if (match_method(m, n, s)) \ - return vmIntrinsics::id; \ - } } - VM_INTRINSICS_DO(VM_INTRINSIC_MATCH, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - return vmIntrinsics::_none; -#undef VM_INTRINSIC_MATCH -} - -void vmIntrinsics::verify_method(ID actual_id, Method* m) { - Symbol* mk = m->method_holder()->name(); - ID declared_id = match_method_with_klass(m, mk); - - if (declared_id == actual_id) return; // success - - if (declared_id == _none && actual_id != _none && mk == vmSymbols::java_lang_StrictMath()) { - // Here are a few special cases in StrictMath not declared in vmSymbols.hpp. - switch (actual_id) { - case _min: - case _max: - case _dsqrt: - declared_id = match_method_with_klass(m, vmSymbols::java_lang_Math()); - if (declared_id == actual_id) return; // acceptable alias - break; - default: - break; - } - } - - const char* declared_name = name_at(declared_id); - const char* actual_name = name_at(actual_id); - m = NULL; - ttyLocker ttyl; - if (xtty != NULL) { - xtty->begin_elem("intrinsic_misdeclared actual='%s' declared='%s'", - actual_name, declared_name); - xtty->method(m); - xtty->end_elem("%s", ""); - } - if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):", - declared_name, declared_id, actual_name, actual_id); - m->print_short_name(tty); - tty->cr(); - } -} -#endif //PRODUCT diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 9b02ce02f99..77b9661c301 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -30,6 +30,7 @@ #include "memory/iterator.hpp" #include "oops/symbol.hpp" #include "utilities/macros.hpp" +#include "vmIntrinsics.hpp" // The class vmSymbols is a name space for fast lookup of @@ -130,6 +131,7 @@ template(java_lang_Record, "java/lang/Record") \ \ template(jdk_internal_loader_NativeLibraries, "jdk/internal/loader/NativeLibraries") \ + template(jdk_internal_loader_BuiltinClassLoader, "jdk/internal/loader/BuiltinClassLoader") \ template(jdk_internal_loader_ClassLoaders_AppClassLoader, "jdk/internal/loader/ClassLoaders$AppClassLoader") \ template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \ \ @@ -664,858 +666,14 @@ \ /* cds */ \ template(jdk_internal_loader_ClassLoaders, "jdk/internal/loader/ClassLoaders") \ + template(java_util_concurrent_ConcurrentHashMap, "java/util/concurrent/ConcurrentHashMap") \ + template(java_util_ArrayList, "java/util/ArrayList") \ template(toFileURL_name, "toFileURL") \ template(toFileURL_signature, "(Ljava/lang/String;)Ljava/net/URL;") \ template(url_void_signature, "(Ljava/net/URL;)V") \ \ /*end*/ -// Here are all the intrinsics known to the runtime and the CI. -// Each intrinsic consists of a public enum name (like _hashCode), -// followed by a specification of its klass, name, and signature: -// template(<id>, <klass>, <name>, <sig>, <FCODE>) -// -// If you add an intrinsic here, you must also define its name -// and signature as members of the VM symbols. The VM symbols for -// the intrinsic name and signature may be defined above. -// -// Because the VM_SYMBOLS_DO macro makes reference to VM_INTRINSICS_DO, -// you can also define an intrinsic's name and/or signature locally to the -// intrinsic, if this makes sense. (It often does make sense.) -// -// For example: -// do_intrinsic(_foo, java_lang_Object, foo_name, foo_signature, F_xx) -// do_name( foo_name, "foo") -// do_signature(foo_signature, "()F") -// klass = vmSymbols::java_lang_Object() -// name = vmSymbols::foo_name() -// signature = vmSymbols::foo_signature() -// -// The name and/or signature might be a "well known" symbol -// like "equal" or "()I", in which case there will be no local -// re-definition of the symbol. -// -// The do_class, do_name, and do_signature calls are all used for the -// same purpose: Define yet another VM symbol. They could all be merged -// into a common 'do_symbol' call, but it seems useful to record our -// intentions here about kinds of symbols (class vs. name vs. signature). -// -// The F_xx is one of the Flags enum; see below. -// -// for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t)) -// -// -// There are two types of intrinsic methods: (1) Library intrinsics and (2) bytecode intrinsics. -// -// (1) A library intrinsic method may be replaced with hand-crafted assembly code, -// with hand-crafted compiler IR, or with a combination of the two. The semantics -// of the replacement code may differ from the semantics of the replaced code. -// -// (2) Bytecode intrinsic methods are not replaced by special code, but they are -// treated in some other special way by the compiler. For example, the compiler -// may delay inlining for some String-related intrinsic methods (e.g., some methods -// defined in the StringBuilder and StringBuffer classes, see -// Compile::should_delay_string_inlining() for more details). -// -// Due to the difference between the semantics of an intrinsic method as defined -// in the (Java) source code and the semantics of the method as defined -// by the code in the VM, intrinsic methods must be explicitly marked. -// -// Intrinsic methods are marked by the jdk.internal.HotSpotIntrinsicCandidate -// annotation. If CheckIntrinsics is enabled, the VM performs the following -// checks when a class C is loaded: (1) all intrinsics defined by the VM for -// class C are present in the loaded class file and are marked; -// (2) an intrinsic is defined by the VM for all marked methods of class C; -// (3) check for orphan methods in class C (i.e., methods for which the VM -// declares an intrinsic but that are not declared for the loaded class C. -// Check (3) is available only in debug builds. -// -// If a mismatch is detected for a method, the VM behaves differently depending -// on the type of build. A fastdebug build exits and reports an error on a mismatch. -// A product build will not replace an unmarked library intrinsic method with -// hand-crafted code, that is, unmarked library intrinsics are treated as ordinary -// methods in a product build. The special treatment of a bytecode intrinsic method -// persists even if the method not marked. -// -// When adding an intrinsic for a method, please make sure to appropriately -// annotate the method in the source code. The list below contains all -// library intrinsics followed by bytecode intrinsics. Please also make sure to -// add the declaration of the intrinsic to the approriate section of the list. -#define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \ - /* (1) Library intrinsics */ \ - do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \ - do_name( hashCode_name, "hashCode") \ - do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \ - do_name( getClass_name, "getClass") \ - do_intrinsic(_clone, java_lang_Object, clone_name, void_object_signature, F_R) \ - do_name( clone_name, "clone") \ - do_intrinsic(_notify, java_lang_Object, notify_name, void_method_signature, F_R) \ - do_name( notify_name, "notify") \ - do_intrinsic(_notifyAll, java_lang_Object, notifyAll_name, void_method_signature, F_R) \ - do_name( notifyAll_name, "notifyAll") \ - \ - /* Math & StrictMath intrinsics are defined in terms of just a few signatures: */ \ - do_class(java_lang_Math, "java/lang/Math") \ - do_class(java_lang_StrictMath, "java/lang/StrictMath") \ - do_signature(double2_double_signature, "(DD)D") \ - do_signature(double3_double_signature, "(DDD)D") \ - do_signature(float2_float_signature, "(FF)F") \ - do_signature(float3_float_signature, "(FFF)F") \ - do_signature(int2_int_signature, "(II)I") \ - do_signature(long2_long_signature, "(JJ)J") \ - \ - /* here are the math names, all together: */ \ - do_name(abs_name,"abs") do_name(sin_name,"sin") do_name(cos_name,"cos") \ - do_name(tan_name,"tan") do_name(atan2_name,"atan2") do_name(sqrt_name,"sqrt") \ - do_name(log_name,"log") do_name(log10_name,"log10") do_name(pow_name,"pow") \ - do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \ - do_name(floor_name, "floor") do_name(ceil_name, "ceil") do_name(rint_name, "rint") \ - \ - do_name(addExact_name,"addExact") \ - do_name(decrementExact_name,"decrementExact") \ - do_name(incrementExact_name,"incrementExact") \ - do_name(multiplyExact_name,"multiplyExact") \ - do_name(multiplyHigh_name,"multiplyHigh") \ - do_name(negateExact_name,"negateExact") \ - do_name(subtractExact_name,"subtractExact") \ - do_name(fma_name, "fma") \ - do_name(copySign_name, "copySign") \ - do_name(signum_name,"signum") \ - \ - do_intrinsic(_dabs, java_lang_Math, abs_name, double_double_signature, F_S) \ - do_intrinsic(_fabs, java_lang_Math, abs_name, float_float_signature, F_S) \ - do_intrinsic(_iabs, java_lang_Math, abs_name, int_int_signature, F_S) \ - do_intrinsic(_labs, java_lang_Math, abs_name, long_long_signature, F_S) \ - do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \ - do_intrinsic(_floor, java_lang_Math, floor_name, double_double_signature, F_S) \ - do_intrinsic(_ceil, java_lang_Math, ceil_name, double_double_signature, F_S) \ - do_intrinsic(_rint, java_lang_Math, rint_name, double_double_signature, F_S) \ - do_intrinsic(_dcos, java_lang_Math, cos_name, double_double_signature, F_S) \ - do_intrinsic(_dtan, java_lang_Math, tan_name, double_double_signature, F_S) \ - do_intrinsic(_datan2, java_lang_Math, atan2_name, double2_double_signature, F_S) \ - do_intrinsic(_dsqrt, java_lang_Math, sqrt_name, double_double_signature, F_S) \ - do_intrinsic(_dlog, java_lang_Math, log_name, double_double_signature, F_S) \ - do_intrinsic(_dlog10, java_lang_Math, log10_name, double_double_signature, F_S) \ - do_intrinsic(_dpow, java_lang_Math, pow_name, double2_double_signature, F_S) \ - do_intrinsic(_dexp, java_lang_Math, exp_name, double_double_signature, F_S) \ - do_intrinsic(_min, java_lang_Math, min_name, int2_int_signature, F_S) \ - do_intrinsic(_max, java_lang_Math, max_name, int2_int_signature, F_S) \ - do_intrinsic(_addExactI, java_lang_Math, addExact_name, int2_int_signature, F_S) \ - do_intrinsic(_addExactL, java_lang_Math, addExact_name, long2_long_signature, F_S) \ - do_intrinsic(_decrementExactI, java_lang_Math, decrementExact_name, int_int_signature, F_S) \ - do_intrinsic(_decrementExactL, java_lang_Math, decrementExact_name, long_long_signature, F_S) \ - do_intrinsic(_incrementExactI, java_lang_Math, incrementExact_name, int_int_signature, F_S) \ - do_intrinsic(_incrementExactL, java_lang_Math, incrementExact_name, long_long_signature, F_S) \ - do_intrinsic(_multiplyExactI, java_lang_Math, multiplyExact_name, int2_int_signature, F_S) \ - do_intrinsic(_multiplyExactL, java_lang_Math, multiplyExact_name, long2_long_signature, F_S) \ - do_intrinsic(_multiplyHigh, java_lang_Math, multiplyHigh_name, long2_long_signature, F_S) \ - do_intrinsic(_negateExactI, java_lang_Math, negateExact_name, int_int_signature, F_S) \ - do_intrinsic(_negateExactL, java_lang_Math, negateExact_name, long_long_signature, F_S) \ - do_intrinsic(_subtractExactI, java_lang_Math, subtractExact_name, int2_int_signature, F_S) \ - do_intrinsic(_subtractExactL, java_lang_Math, subtractExact_name, long2_long_signature, F_S) \ - do_intrinsic(_fmaD, java_lang_Math, fma_name, double3_double_signature, F_S) \ - do_intrinsic(_fmaF, java_lang_Math, fma_name, float3_float_signature, F_S) \ - do_intrinsic(_maxF, java_lang_Math, max_name, float2_float_signature, F_S) \ - do_intrinsic(_minF, java_lang_Math, min_name, float2_float_signature, F_S) \ - do_intrinsic(_maxD, java_lang_Math, max_name, double2_double_signature, F_S) \ - do_intrinsic(_minD, java_lang_Math, min_name, double2_double_signature, F_S) \ - do_intrinsic(_dcopySign, java_lang_Math, copySign_name, double2_double_signature, F_S) \ - do_intrinsic(_fcopySign, java_lang_Math, copySign_name, float2_float_signature, F_S) \ - do_intrinsic(_dsignum, java_lang_Math, signum_name, double_double_signature, F_S) \ - do_intrinsic(_fsignum, java_lang_Math, signum_name, float_float_signature, F_S) \ - \ - do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_S) \ - do_name( floatToRawIntBits_name, "floatToRawIntBits") \ - do_intrinsic(_floatToIntBits, java_lang_Float, floatToIntBits_name, float_int_signature, F_S) \ - do_name( floatToIntBits_name, "floatToIntBits") \ - do_intrinsic(_intBitsToFloat, java_lang_Float, intBitsToFloat_name, int_float_signature, F_S) \ - do_name( intBitsToFloat_name, "intBitsToFloat") \ - do_intrinsic(_doubleToRawLongBits, java_lang_Double, doubleToRawLongBits_name, double_long_signature, F_S) \ - do_name( doubleToRawLongBits_name, "doubleToRawLongBits") \ - do_intrinsic(_doubleToLongBits, java_lang_Double, doubleToLongBits_name, double_long_signature, F_S) \ - do_name( doubleToLongBits_name, "doubleToLongBits") \ - do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \ - do_name( longBitsToDouble_name, "longBitsToDouble") \ - \ - do_intrinsic(_numberOfLeadingZeros_i, java_lang_Integer, numberOfLeadingZeros_name,int_int_signature, F_S) \ - do_intrinsic(_numberOfLeadingZeros_l, java_lang_Long, numberOfLeadingZeros_name,long_int_signature, F_S) \ - \ - do_intrinsic(_numberOfTrailingZeros_i, java_lang_Integer, numberOfTrailingZeros_name,int_int_signature, F_S) \ - do_intrinsic(_numberOfTrailingZeros_l, java_lang_Long, numberOfTrailingZeros_name,long_int_signature, F_S) \ - \ - do_intrinsic(_bitCount_i, java_lang_Integer, bitCount_name, int_int_signature, F_S) \ - do_intrinsic(_bitCount_l, java_lang_Long, bitCount_name, long_int_signature, F_S) \ - \ - do_intrinsic(_reverseBytes_i, java_lang_Integer, reverseBytes_name, int_int_signature, F_S) \ - do_name( reverseBytes_name, "reverseBytes") \ - do_intrinsic(_reverseBytes_l, java_lang_Long, reverseBytes_name, long_long_signature, F_S) \ - /* (symbol reverseBytes_name defined above) */ \ - do_intrinsic(_reverseBytes_c, java_lang_Character, reverseBytes_name, char_char_signature, F_S) \ - /* (symbol reverseBytes_name defined above) */ \ - do_intrinsic(_reverseBytes_s, java_lang_Short, reverseBytes_name, short_short_signature, F_S) \ - /* (symbol reverseBytes_name defined above) */ \ - \ - do_intrinsic(_identityHashCode, java_lang_System, identityHashCode_name, object_int_signature, F_S) \ - do_name( identityHashCode_name, "identityHashCode") \ - do_intrinsic(_currentTimeMillis, java_lang_System, currentTimeMillis_name, void_long_signature, F_S) \ - \ - do_name( currentTimeMillis_name, "currentTimeMillis") \ - do_intrinsic(_nanoTime, java_lang_System, nanoTime_name, void_long_signature, F_S) \ - do_name( nanoTime_name, "nanoTime") \ - \ - JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \ - \ - do_intrinsic(_arraycopy, java_lang_System, arraycopy_name, arraycopy_signature, F_S) \ - do_name( arraycopy_name, "arraycopy") \ - do_signature(arraycopy_signature, "(Ljava/lang/Object;ILjava/lang/Object;II)V") \ - do_intrinsic(_currentThread, java_lang_Thread, currentThread_name, currentThread_signature, F_S) \ - do_name( currentThread_name, "currentThread") \ - do_signature(currentThread_signature, "()Ljava/lang/Thread;") \ - \ - /* reflective intrinsics, for java/lang/Class, etc. */ \ - do_intrinsic(_isAssignableFrom, java_lang_Class, isAssignableFrom_name, class_boolean_signature, F_RN) \ - do_name( isAssignableFrom_name, "isAssignableFrom") \ - do_intrinsic(_isInstance, java_lang_Class, isInstance_name, object_boolean_signature, F_RN) \ - do_name( isInstance_name, "isInstance") \ - do_intrinsic(_getModifiers, java_lang_Class, getModifiers_name, void_int_signature, F_RN) \ - do_name( getModifiers_name, "getModifiers") \ - do_intrinsic(_isInterface, java_lang_Class, isInterface_name, void_boolean_signature, F_RN) \ - do_name( isInterface_name, "isInterface") \ - do_intrinsic(_isArray, java_lang_Class, isArray_name, void_boolean_signature, F_RN) \ - do_name( isArray_name, "isArray") \ - do_intrinsic(_isPrimitive, java_lang_Class, isPrimitive_name, void_boolean_signature, F_RN) \ - do_name( isPrimitive_name, "isPrimitive") \ - do_intrinsic(_isHidden, java_lang_Class, isHidden_name, void_boolean_signature, F_RN) \ - do_name( isHidden_name, "isHidden") \ - do_intrinsic(_getSuperclass, java_lang_Class, getSuperclass_name, void_class_signature, F_RN) \ - do_name( getSuperclass_name, "getSuperclass") \ - do_intrinsic(_Class_cast, java_lang_Class, Class_cast_name, object_object_signature, F_R) \ - do_name( Class_cast_name, "cast") \ - \ - do_intrinsic(_getClassAccessFlags, reflect_Reflection, getClassAccessFlags_name, class_int_signature, F_SN) \ - do_name( getClassAccessFlags_name, "getClassAccessFlags") \ - do_intrinsic(_getLength, java_lang_reflect_Array, getLength_name, object_int_signature, F_SN) \ - do_name( getLength_name, "getLength") \ - \ - do_intrinsic(_getCallerClass, reflect_Reflection, getCallerClass_name, void_class_signature, F_SN) \ - do_name( getCallerClass_name, "getCallerClass") \ - \ - do_intrinsic(_newArray, java_lang_reflect_Array, newArray_name, newArray_signature, F_SN) \ - do_name( newArray_name, "newArray") \ - do_signature(newArray_signature, "(Ljava/lang/Class;I)Ljava/lang/Object;") \ - \ - do_intrinsic(_onSpinWait, java_lang_Thread, onSpinWait_name, onSpinWait_signature, F_S) \ - do_name( onSpinWait_name, "onSpinWait") \ - do_alias( onSpinWait_signature, void_method_signature) \ - \ - do_intrinsic(_copyOf, java_util_Arrays, copyOf_name, copyOf_signature, F_S) \ - do_name( copyOf_name, "copyOf") \ - do_signature(copyOf_signature, "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;") \ - \ - do_intrinsic(_copyOfRange, java_util_Arrays, copyOfRange_name, copyOfRange_signature, F_S) \ - do_name( copyOfRange_name, "copyOfRange") \ - do_signature(copyOfRange_signature, "([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;") \ - \ - do_intrinsic(_equalsC, java_util_Arrays, equals_name, equalsC_signature, F_S) \ - do_signature(equalsC_signature, "([C[C)Z") \ - do_intrinsic(_equalsB, java_util_Arrays, equals_name, equalsB_signature, F_S) \ - do_signature(equalsB_signature, "([B[B)Z") \ - \ - do_intrinsic(_compressStringC, java_lang_StringUTF16, compress_name, encodeISOArray_signature, F_S) \ - do_name( compress_name, "compress") \ - do_intrinsic(_compressStringB, java_lang_StringUTF16, compress_name, indexOfI_signature, F_S) \ - do_intrinsic(_inflateStringC, java_lang_StringLatin1, inflate_name, inflateC_signature, F_S) \ - do_name( inflate_name, "inflate") \ - do_signature(inflateC_signature, "([BI[CII)V") \ - do_intrinsic(_inflateStringB, java_lang_StringLatin1, inflate_name, inflateB_signature, F_S) \ - do_signature(inflateB_signature, "([BI[BII)V") \ - do_intrinsic(_toBytesStringU, java_lang_StringUTF16, toBytes_name, toBytesU_signature, F_S) \ - do_name( toBytes_name, "toBytes") \ - do_signature(toBytesU_signature, "([CII)[B") \ - do_intrinsic(_getCharsStringU, java_lang_StringUTF16, getCharsU_name, getCharsU_signature, F_S) \ - do_name( getCharsU_name, "getChars") \ - do_signature(getCharsU_signature, "([BII[CI)V") \ - do_intrinsic(_getCharStringU, java_lang_StringUTF16, getChar_name, getCharStringU_signature, F_S) \ - do_signature(getCharStringU_signature, "([BI)C") \ - do_intrinsic(_putCharStringU, java_lang_StringUTF16, putChar_name, putCharStringU_signature, F_S) \ - do_signature(putCharStringU_signature, "([BII)V") \ - do_intrinsic(_compareToL, java_lang_StringLatin1,compareTo_name, compareTo_indexOf_signature, F_S) \ - do_intrinsic(_compareToU, java_lang_StringUTF16, compareTo_name, compareTo_indexOf_signature, F_S) \ - do_intrinsic(_compareToLU, java_lang_StringLatin1,compareToLU_name, compareTo_indexOf_signature, F_S) \ - do_intrinsic(_compareToUL, java_lang_StringUTF16, compareToUL_name, compareTo_indexOf_signature, F_S) \ - do_signature(compareTo_indexOf_signature, "([B[B)I") \ - do_name( compareTo_name, "compareTo") \ - do_name( compareToLU_name, "compareToUTF16") \ - do_name( compareToUL_name, "compareToLatin1") \ - do_intrinsic(_indexOfL, java_lang_StringLatin1,indexOf_name, compareTo_indexOf_signature, F_S) \ - do_intrinsic(_indexOfU, java_lang_StringUTF16, indexOf_name, compareTo_indexOf_signature, F_S) \ - do_intrinsic(_indexOfUL, java_lang_StringUTF16, indexOfUL_name, compareTo_indexOf_signature, F_S) \ - do_intrinsic(_indexOfIL, java_lang_StringLatin1,indexOf_name, indexOfI_signature, F_S) \ - do_intrinsic(_indexOfIU, java_lang_StringUTF16, indexOf_name, indexOfI_signature, F_S) \ - do_intrinsic(_indexOfIUL, java_lang_StringUTF16, indexOfUL_name, indexOfI_signature, F_S) \ - do_intrinsic(_indexOfU_char, java_lang_StringUTF16, indexOfChar_name, indexOfChar_signature, F_S) \ - do_name( indexOf_name, "indexOf") \ - do_name( indexOfChar_name, "indexOfChar") \ - do_name( indexOfUL_name, "indexOfLatin1") \ - do_signature(indexOfI_signature, "([BI[BII)I") \ - do_signature(indexOfChar_signature, "([BIII)I") \ - do_intrinsic(_equalsL, java_lang_StringLatin1,equals_name, equalsB_signature, F_S) \ - do_intrinsic(_equalsU, java_lang_StringUTF16, equals_name, equalsB_signature, F_S) \ - \ - do_intrinsic(_isDigit, java_lang_CharacterDataLatin1, isDigit_name, int_bool_signature, F_R) \ - do_name( isDigit_name, "isDigit") \ - do_intrinsic(_isLowerCase, java_lang_CharacterDataLatin1, isLowerCase_name, int_bool_signature, F_R) \ - do_name( isLowerCase_name, "isLowerCase") \ - do_intrinsic(_isUpperCase, java_lang_CharacterDataLatin1, isUpperCase_name, int_bool_signature, F_R) \ - do_name( isUpperCase_name, "isUpperCase") \ - do_intrinsic(_isWhitespace, java_lang_CharacterDataLatin1, isWhitespace_name, int_bool_signature, F_R) \ - do_name( isWhitespace_name, "isWhitespace") \ - \ - do_intrinsic(_Preconditions_checkIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkIndex_signature, F_S) \ - do_signature(Preconditions_checkIndex_signature, "(IILjava/util/function/BiFunction;)I") \ - \ - do_class(java_nio_Buffer, "java/nio/Buffer") \ - do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \ - do_name( checkIndex_name, "checkIndex") \ - \ - do_class(java_lang_StringCoding, "java/lang/StringCoding") \ - do_intrinsic(_hasNegatives, java_lang_StringCoding, hasNegatives_name, hasNegatives_signature, F_S) \ - do_name( hasNegatives_name, "hasNegatives") \ - do_signature(hasNegatives_signature, "([BII)Z") \ - \ - do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ - do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ - do_name( encodeISOArray_name, "implEncodeISOArray") \ - do_signature(encodeISOArray_signature, "([CI[BII)I") \ - \ - do_intrinsic(_encodeByteISOArray, java_lang_StringCoding, encodeISOArray_name, indexOfI_signature, F_S) \ - \ - do_class(java_math_BigInteger, "java/math/BigInteger") \ - do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \ - do_name( multiplyToLen_name, "implMultiplyToLen") \ - do_signature(multiplyToLen_signature, "([II[II[I)[I") \ - \ - do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \ - do_name( squareToLen_name, "implSquareToLen") \ - do_signature(squareToLen_signature, "([II[II)[I") \ - \ - do_intrinsic(_mulAdd, java_math_BigInteger, mulAdd_name, mulAdd_signature, F_S) \ - do_name( mulAdd_name, "implMulAdd") \ - do_signature(mulAdd_signature, "([I[IIII)I") \ - \ - do_intrinsic(_montgomeryMultiply, java_math_BigInteger, montgomeryMultiply_name, montgomeryMultiply_signature, F_S) \ - do_name( montgomeryMultiply_name, "implMontgomeryMultiply") \ - do_signature(montgomeryMultiply_signature, "([I[I[IIJ[I)[I") \ - \ - do_intrinsic(_montgomerySquare, java_math_BigInteger, montgomerySquare_name, montgomerySquare_signature, F_S) \ - do_name( montgomerySquare_name, "implMontgomerySquare") \ - do_signature(montgomerySquare_signature, "([I[IIJ[I)[I") \ - \ - do_intrinsic(_bigIntegerRightShiftWorker, java_math_BigInteger, rightShift_name, big_integer_shift_worker_signature, F_S) \ - do_name( rightShift_name, "shiftRightImplWorker") \ - \ - do_intrinsic(_bigIntegerLeftShiftWorker, java_math_BigInteger, leftShift_name, big_integer_shift_worker_signature, F_S) \ - do_name( leftShift_name, "shiftLeftImplWorker") \ - \ - do_class(jdk_internal_util_ArraysSupport, "jdk/internal/util/ArraysSupport") \ - do_intrinsic(_vectorizedMismatch, jdk_internal_util_ArraysSupport, vectorizedMismatch_name, vectorizedMismatch_signature, F_S)\ - do_name(vectorizedMismatch_name, "vectorizedMismatch") \ - do_signature(vectorizedMismatch_signature, "(Ljava/lang/Object;JLjava/lang/Object;JII)I") \ - \ - /* java/lang/ref/Reference */ \ - do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ - \ - /* support for com.sun.crypto.provider.AESCrypt and some of its callers */ \ - do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \ - do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ - do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ - do_name( encryptBlock_name, "implEncryptBlock") \ - do_name( decryptBlock_name, "implDecryptBlock") \ - do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \ - \ - do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \ - do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ - do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ - do_name( encrypt_name, "implEncrypt") \ - do_name( decrypt_name, "implDecrypt") \ - do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \ - \ - do_class(com_sun_crypto_provider_electronicCodeBook, "com/sun/crypto/provider/ElectronicCodeBook") \ - do_intrinsic(_electronicCodeBook_encryptAESCrypt, com_sun_crypto_provider_electronicCodeBook, ecb_encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ - do_intrinsic(_electronicCodeBook_decryptAESCrypt, com_sun_crypto_provider_electronicCodeBook, ecb_decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ - do_name(ecb_encrypt_name, "implECBEncrypt") \ - do_name(ecb_decrypt_name, "implECBDecrypt") \ - \ - do_class(com_sun_crypto_provider_counterMode, "com/sun/crypto/provider/CounterMode") \ - do_intrinsic(_counterMode_AESCrypt, com_sun_crypto_provider_counterMode, crypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ - do_name( crypt_name, "implCrypt") \ - \ - /* support for sun.security.provider.MD5 */ \ - do_class(sun_security_provider_md5, "sun/security/provider/MD5") \ - do_intrinsic(_md5_implCompress, sun_security_provider_md5, implCompress_name, implCompress_signature, F_R) \ - do_name( implCompress_name, "implCompress0") \ - do_signature(implCompress_signature, "([BI)V") \ - \ - /* support for sun.security.provider.SHA */ \ - do_class(sun_security_provider_sha, "sun/security/provider/SHA") \ - do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \ - \ - /* support for sun.security.provider.SHA2 */ \ - do_class(sun_security_provider_sha2, "sun/security/provider/SHA2") \ - do_intrinsic(_sha2_implCompress, sun_security_provider_sha2, implCompress_name, implCompress_signature, F_R) \ - \ - /* support for sun.security.provider.SHA5 */ \ - do_class(sun_security_provider_sha5, "sun/security/provider/SHA5") \ - do_intrinsic(_sha5_implCompress, sun_security_provider_sha5, implCompress_name, implCompress_signature, F_R) \ - \ - /* support for sun.security.provider.DigestBase */ \ - do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \ - do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \ - do_name( implCompressMB_name, "implCompressMultiBlock0") \ - do_signature(implCompressMB_signature, "([BII)I") \ - \ - /* support for java.util.Base64.Encoder*/ \ - do_class(java_util_Base64_Encoder, "java/util/Base64$Encoder") \ - do_intrinsic(_base64_encodeBlock, java_util_Base64_Encoder, encodeBlock_name, encodeBlock_signature, F_R) \ - do_name(encodeBlock_name, "encodeBlock") \ - do_signature(encodeBlock_signature, "([BII[BIZ)V") \ - \ - /* support for com.sun.crypto.provider.GHASH */ \ - do_class(com_sun_crypto_provider_ghash, "com/sun/crypto/provider/GHASH") \ - do_intrinsic(_ghash_processBlocks, com_sun_crypto_provider_ghash, processBlocks_name, ghash_processBlocks_signature, F_S) \ - do_name(processBlocks_name, "processBlocks") \ - do_signature(ghash_processBlocks_signature, "([BII[J[J)V") \ - \ - /* support for java.util.zip */ \ - do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \ - do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \ - do_name( update_name, "update") \ - do_intrinsic(_updateBytesCRC32, java_util_zip_CRC32, updateBytes_name, updateBytes_signature, F_SN) \ - do_name( updateBytes_name, "updateBytes0") \ - do_signature(updateBytes_signature, "(I[BII)I") \ - do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \ - do_name( updateByteBuffer_name, "updateByteBuffer0") \ - do_signature(updateByteBuffer_signature, "(IJII)I") \ - \ - /* support for java.util.zip.CRC32C */ \ - do_class(java_util_zip_CRC32C, "java/util/zip/CRC32C") \ - do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_C_name, updateBytes_signature, F_S) \ - do_name( updateBytes_C_name, "updateBytes") \ - do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_C_name, updateByteBuffer_signature, F_S) \ - do_name( updateDirectByteBuffer_C_name, "updateDirectByteBuffer") \ - \ - /* support for java.util.zip.Adler32 */ \ - do_class(java_util_zip_Adler32, "java/util/zip/Adler32") \ - do_intrinsic(_updateBytesAdler32, java_util_zip_Adler32, updateBytes_C_name, updateBytes_signature, F_SN) \ - do_intrinsic(_updateByteBufferAdler32, java_util_zip_Adler32, updateByteBuffer_A_name, updateByteBuffer_signature, F_SN) \ - do_name( updateByteBuffer_A_name, "updateByteBuffer") \ - \ - /* support for UnsafeConstants */ \ - do_class(jdk_internal_misc_UnsafeConstants, "jdk/internal/misc/UnsafeConstants") \ - \ - /* support for Unsafe */ \ - do_class(jdk_internal_misc_Unsafe, "jdk/internal/misc/Unsafe") \ - do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ - \ - do_intrinsic(_writeback0, jdk_internal_misc_Unsafe, writeback0_name, long_void_signature , F_RN) \ - do_name( writeback0_name, "writeback0") \ - do_intrinsic(_writebackPreSync0, jdk_internal_misc_Unsafe, writebackPreSync0_name, void_method_signature , F_RN) \ - do_name( writebackPreSync0_name, "writebackPreSync0") \ - do_intrinsic(_writebackPostSync0, jdk_internal_misc_Unsafe, writebackPostSync0_name, void_method_signature , F_RN) \ - do_name( writebackPostSync0_name, "writebackPostSync0") \ - do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \ - do_name( allocateInstance_name, "allocateInstance") \ - do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \ - do_intrinsic(_allocateUninitializedArray, jdk_internal_misc_Unsafe, allocateUninitializedArray_name, newArray_signature, F_R) \ - do_name( allocateUninitializedArray_name, "allocateUninitializedArray0") \ - do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ - do_name( copyMemory_name, "copyMemory0") \ - do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ - do_intrinsic(_loadFence, jdk_internal_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ - do_name( loadFence_name, "loadFence") \ - do_alias( loadFence_signature, void_method_signature) \ - do_intrinsic(_storeFence, jdk_internal_misc_Unsafe, storeFence_name, storeFence_signature, F_RN) \ - do_name( storeFence_name, "storeFence") \ - do_alias( storeFence_signature, void_method_signature) \ - do_intrinsic(_fullFence, jdk_internal_misc_Unsafe, fullFence_name, fullFence_signature, F_RN) \ - do_name( fullFence_name, "fullFence") \ - do_alias( fullFence_signature, void_method_signature) \ - \ - /* Custom branch frequencies profiling support for JSR292 */ \ - do_class(java_lang_invoke_MethodHandleImpl, "java/lang/invoke/MethodHandleImpl") \ - do_intrinsic(_profileBoolean, java_lang_invoke_MethodHandleImpl, profileBoolean_name, profileBoolean_signature, F_S) \ - do_name( profileBoolean_name, "profileBoolean") \ - do_signature(profileBoolean_signature, "(Z[I)Z") \ - do_intrinsic(_isCompileConstant, java_lang_invoke_MethodHandleImpl, isCompileConstant_name, isCompileConstant_signature, F_S) \ - do_name( isCompileConstant_name, "isCompileConstant") \ - do_alias( isCompileConstant_signature, object_boolean_signature) \ - \ - /* unsafe memory references (there are a lot of them...) */ \ - do_signature(getReference_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \ - do_signature(putReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \ - do_signature(getBoolean_signature, "(Ljava/lang/Object;J)Z") \ - do_signature(putBoolean_signature, "(Ljava/lang/Object;JZ)V") \ - do_signature(getByte_signature, "(Ljava/lang/Object;J)B") \ - do_signature(putByte_signature, "(Ljava/lang/Object;JB)V") \ - do_signature(getShort_signature, "(Ljava/lang/Object;J)S") \ - do_signature(putShort_signature, "(Ljava/lang/Object;JS)V") \ - do_signature(getChar_signature, "(Ljava/lang/Object;J)C") \ - do_signature(putChar_signature, "(Ljava/lang/Object;JC)V") \ - do_signature(getInt_signature, "(Ljava/lang/Object;J)I") \ - do_signature(putInt_signature, "(Ljava/lang/Object;JI)V") \ - do_signature(getLong_signature, "(Ljava/lang/Object;J)J") \ - do_signature(putLong_signature, "(Ljava/lang/Object;JJ)V") \ - do_signature(getFloat_signature, "(Ljava/lang/Object;J)F") \ - do_signature(putFloat_signature, "(Ljava/lang/Object;JF)V") \ - do_signature(getDouble_signature, "(Ljava/lang/Object;J)D") \ - do_signature(putDouble_signature, "(Ljava/lang/Object;JD)V") \ - \ - do_name(getReference_name,"getReference") do_name(putReference_name,"putReference") \ - do_name(getBoolean_name,"getBoolean") do_name(putBoolean_name,"putBoolean") \ - do_name(getByte_name,"getByte") do_name(putByte_name,"putByte") \ - do_name(getShort_name,"getShort") do_name(putShort_name,"putShort") \ - do_name(getChar_name,"getChar") do_name(putChar_name,"putChar") \ - do_name(getInt_name,"getInt") do_name(putInt_name,"putInt") \ - do_name(getLong_name,"getLong") do_name(putLong_name,"putLong") \ - do_name(getFloat_name,"getFloat") do_name(putFloat_name,"putFloat") \ - do_name(getDouble_name,"getDouble") do_name(putDouble_name,"putDouble") \ - \ - do_intrinsic(_getReference, jdk_internal_misc_Unsafe, getReference_name, getReference_signature, F_RN) \ - do_intrinsic(_getBoolean, jdk_internal_misc_Unsafe, getBoolean_name, getBoolean_signature, F_RN) \ - do_intrinsic(_getByte, jdk_internal_misc_Unsafe, getByte_name, getByte_signature, F_RN) \ - do_intrinsic(_getShort, jdk_internal_misc_Unsafe, getShort_name, getShort_signature, F_RN) \ - do_intrinsic(_getChar, jdk_internal_misc_Unsafe, getChar_name, getChar_signature, F_RN) \ - do_intrinsic(_getInt, jdk_internal_misc_Unsafe, getInt_name, getInt_signature, F_RN) \ - do_intrinsic(_getLong, jdk_internal_misc_Unsafe, getLong_name, getLong_signature, F_RN) \ - do_intrinsic(_getFloat, jdk_internal_misc_Unsafe, getFloat_name, getFloat_signature, F_RN) \ - do_intrinsic(_getDouble, jdk_internal_misc_Unsafe, getDouble_name, getDouble_signature, F_RN) \ - do_intrinsic(_putReference, jdk_internal_misc_Unsafe, putReference_name, putReference_signature, F_RN) \ - do_intrinsic(_putBoolean, jdk_internal_misc_Unsafe, putBoolean_name, putBoolean_signature, F_RN) \ - do_intrinsic(_putByte, jdk_internal_misc_Unsafe, putByte_name, putByte_signature, F_RN) \ - do_intrinsic(_putShort, jdk_internal_misc_Unsafe, putShort_name, putShort_signature, F_RN) \ - do_intrinsic(_putChar, jdk_internal_misc_Unsafe, putChar_name, putChar_signature, F_RN) \ - do_intrinsic(_putInt, jdk_internal_misc_Unsafe, putInt_name, putInt_signature, F_RN) \ - do_intrinsic(_putLong, jdk_internal_misc_Unsafe, putLong_name, putLong_signature, F_RN) \ - do_intrinsic(_putFloat, jdk_internal_misc_Unsafe, putFloat_name, putFloat_signature, F_RN) \ - do_intrinsic(_putDouble, jdk_internal_misc_Unsafe, putDouble_name, putDouble_signature, F_RN) \ - \ - do_name(getReferenceVolatile_name,"getReferenceVolatile") do_name(putReferenceVolatile_name,"putReferenceVolatile") \ - do_name(getBooleanVolatile_name,"getBooleanVolatile") do_name(putBooleanVolatile_name,"putBooleanVolatile") \ - do_name(getByteVolatile_name,"getByteVolatile") do_name(putByteVolatile_name,"putByteVolatile") \ - do_name(getShortVolatile_name,"getShortVolatile") do_name(putShortVolatile_name,"putShortVolatile") \ - do_name(getCharVolatile_name,"getCharVolatile") do_name(putCharVolatile_name,"putCharVolatile") \ - do_name(getIntVolatile_name,"getIntVolatile") do_name(putIntVolatile_name,"putIntVolatile") \ - do_name(getLongVolatile_name,"getLongVolatile") do_name(putLongVolatile_name,"putLongVolatile") \ - do_name(getFloatVolatile_name,"getFloatVolatile") do_name(putFloatVolatile_name,"putFloatVolatile") \ - do_name(getDoubleVolatile_name,"getDoubleVolatile") do_name(putDoubleVolatile_name,"putDoubleVolatile") \ - \ - do_intrinsic(_getReferenceVolatile, jdk_internal_misc_Unsafe, getReferenceVolatile_name, getReference_signature, F_RN) \ - do_intrinsic(_getBooleanVolatile, jdk_internal_misc_Unsafe, getBooleanVolatile_name, getBoolean_signature, F_RN) \ - do_intrinsic(_getByteVolatile, jdk_internal_misc_Unsafe, getByteVolatile_name, getByte_signature, F_RN) \ - do_intrinsic(_getShortVolatile, jdk_internal_misc_Unsafe, getShortVolatile_name, getShort_signature, F_RN) \ - do_intrinsic(_getCharVolatile, jdk_internal_misc_Unsafe, getCharVolatile_name, getChar_signature, F_RN) \ - do_intrinsic(_getIntVolatile, jdk_internal_misc_Unsafe, getIntVolatile_name, getInt_signature, F_RN) \ - do_intrinsic(_getLongVolatile, jdk_internal_misc_Unsafe, getLongVolatile_name, getLong_signature, F_RN) \ - do_intrinsic(_getFloatVolatile, jdk_internal_misc_Unsafe, getFloatVolatile_name, getFloat_signature, F_RN) \ - do_intrinsic(_getDoubleVolatile, jdk_internal_misc_Unsafe, getDoubleVolatile_name, getDouble_signature, F_RN) \ - do_intrinsic(_putReferenceVolatile, jdk_internal_misc_Unsafe, putReferenceVolatile_name, putReference_signature, F_RN) \ - do_intrinsic(_putBooleanVolatile, jdk_internal_misc_Unsafe, putBooleanVolatile_name, putBoolean_signature, F_RN) \ - do_intrinsic(_putByteVolatile, jdk_internal_misc_Unsafe, putByteVolatile_name, putByte_signature, F_RN) \ - do_intrinsic(_putShortVolatile, jdk_internal_misc_Unsafe, putShortVolatile_name, putShort_signature, F_RN) \ - do_intrinsic(_putCharVolatile, jdk_internal_misc_Unsafe, putCharVolatile_name, putChar_signature, F_RN) \ - do_intrinsic(_putIntVolatile, jdk_internal_misc_Unsafe, putIntVolatile_name, putInt_signature, F_RN) \ - do_intrinsic(_putLongVolatile, jdk_internal_misc_Unsafe, putLongVolatile_name, putLong_signature, F_RN) \ - do_intrinsic(_putFloatVolatile, jdk_internal_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \ - do_intrinsic(_putDoubleVolatile, jdk_internal_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \ - \ - do_name(getReferenceOpaque_name,"getReferenceOpaque") do_name(putReferenceOpaque_name,"putReferenceOpaque") \ - do_name(getBooleanOpaque_name,"getBooleanOpaque") do_name(putBooleanOpaque_name,"putBooleanOpaque") \ - do_name(getByteOpaque_name,"getByteOpaque") do_name(putByteOpaque_name,"putByteOpaque") \ - do_name(getShortOpaque_name,"getShortOpaque") do_name(putShortOpaque_name,"putShortOpaque") \ - do_name(getCharOpaque_name,"getCharOpaque") do_name(putCharOpaque_name,"putCharOpaque") \ - do_name(getIntOpaque_name,"getIntOpaque") do_name(putIntOpaque_name,"putIntOpaque") \ - do_name(getLongOpaque_name,"getLongOpaque") do_name(putLongOpaque_name,"putLongOpaque") \ - do_name(getFloatOpaque_name,"getFloatOpaque") do_name(putFloatOpaque_name,"putFloatOpaque") \ - do_name(getDoubleOpaque_name,"getDoubleOpaque") do_name(putDoubleOpaque_name,"putDoubleOpaque") \ - \ - do_intrinsic(_getReferenceOpaque, jdk_internal_misc_Unsafe, getReferenceOpaque_name, getReference_signature, F_R) \ - do_intrinsic(_getBooleanOpaque, jdk_internal_misc_Unsafe, getBooleanOpaque_name, getBoolean_signature, F_R) \ - do_intrinsic(_getByteOpaque, jdk_internal_misc_Unsafe, getByteOpaque_name, getByte_signature, F_R) \ - do_intrinsic(_getShortOpaque, jdk_internal_misc_Unsafe, getShortOpaque_name, getShort_signature, F_R) \ - do_intrinsic(_getCharOpaque, jdk_internal_misc_Unsafe, getCharOpaque_name, getChar_signature, F_R) \ - do_intrinsic(_getIntOpaque, jdk_internal_misc_Unsafe, getIntOpaque_name, getInt_signature, F_R) \ - do_intrinsic(_getLongOpaque, jdk_internal_misc_Unsafe, getLongOpaque_name, getLong_signature, F_R) \ - do_intrinsic(_getFloatOpaque, jdk_internal_misc_Unsafe, getFloatOpaque_name, getFloat_signature, F_R) \ - do_intrinsic(_getDoubleOpaque, jdk_internal_misc_Unsafe, getDoubleOpaque_name, getDouble_signature, F_R) \ - do_intrinsic(_putReferenceOpaque, jdk_internal_misc_Unsafe, putReferenceOpaque_name, putReference_signature, F_R) \ - do_intrinsic(_putBooleanOpaque, jdk_internal_misc_Unsafe, putBooleanOpaque_name, putBoolean_signature, F_R) \ - do_intrinsic(_putByteOpaque, jdk_internal_misc_Unsafe, putByteOpaque_name, putByte_signature, F_R) \ - do_intrinsic(_putShortOpaque, jdk_internal_misc_Unsafe, putShortOpaque_name, putShort_signature, F_R) \ - do_intrinsic(_putCharOpaque, jdk_internal_misc_Unsafe, putCharOpaque_name, putChar_signature, F_R) \ - do_intrinsic(_putIntOpaque, jdk_internal_misc_Unsafe, putIntOpaque_name, putInt_signature, F_R) \ - do_intrinsic(_putLongOpaque, jdk_internal_misc_Unsafe, putLongOpaque_name, putLong_signature, F_R) \ - do_intrinsic(_putFloatOpaque, jdk_internal_misc_Unsafe, putFloatOpaque_name, putFloat_signature, F_R) \ - do_intrinsic(_putDoubleOpaque, jdk_internal_misc_Unsafe, putDoubleOpaque_name, putDouble_signature, F_R) \ - \ - do_name(getReferenceAcquire_name, "getReferenceAcquire") do_name(putReferenceRelease_name, "putReferenceRelease") \ - do_name(getBooleanAcquire_name, "getBooleanAcquire") do_name(putBooleanRelease_name, "putBooleanRelease") \ - do_name(getByteAcquire_name, "getByteAcquire") do_name(putByteRelease_name, "putByteRelease") \ - do_name(getShortAcquire_name, "getShortAcquire") do_name(putShortRelease_name, "putShortRelease") \ - do_name(getCharAcquire_name, "getCharAcquire") do_name(putCharRelease_name, "putCharRelease") \ - do_name(getIntAcquire_name, "getIntAcquire") do_name(putIntRelease_name, "putIntRelease") \ - do_name(getLongAcquire_name, "getLongAcquire") do_name(putLongRelease_name, "putLongRelease") \ - do_name(getFloatAcquire_name, "getFloatAcquire") do_name(putFloatRelease_name, "putFloatRelease") \ - do_name(getDoubleAcquire_name, "getDoubleAcquire") do_name(putDoubleRelease_name, "putDoubleRelease") \ - \ - do_intrinsic(_getReferenceAcquire, jdk_internal_misc_Unsafe, getReferenceAcquire_name, getReference_signature, F_R) \ - do_intrinsic(_getBooleanAcquire, jdk_internal_misc_Unsafe, getBooleanAcquire_name, getBoolean_signature, F_R) \ - do_intrinsic(_getByteAcquire, jdk_internal_misc_Unsafe, getByteAcquire_name, getByte_signature, F_R) \ - do_intrinsic(_getShortAcquire, jdk_internal_misc_Unsafe, getShortAcquire_name, getShort_signature, F_R) \ - do_intrinsic(_getCharAcquire, jdk_internal_misc_Unsafe, getCharAcquire_name, getChar_signature, F_R) \ - do_intrinsic(_getIntAcquire, jdk_internal_misc_Unsafe, getIntAcquire_name, getInt_signature, F_R) \ - do_intrinsic(_getLongAcquire, jdk_internal_misc_Unsafe, getLongAcquire_name, getLong_signature, F_R) \ - do_intrinsic(_getFloatAcquire, jdk_internal_misc_Unsafe, getFloatAcquire_name, getFloat_signature, F_R) \ - do_intrinsic(_getDoubleAcquire, jdk_internal_misc_Unsafe, getDoubleAcquire_name, getDouble_signature, F_R) \ - do_intrinsic(_putReferenceRelease, jdk_internal_misc_Unsafe, putReferenceRelease_name, putReference_signature, F_R) \ - do_intrinsic(_putBooleanRelease, jdk_internal_misc_Unsafe, putBooleanRelease_name, putBoolean_signature, F_R) \ - do_intrinsic(_putByteRelease, jdk_internal_misc_Unsafe, putByteRelease_name, putByte_signature, F_R) \ - do_intrinsic(_putShortRelease, jdk_internal_misc_Unsafe, putShortRelease_name, putShort_signature, F_R) \ - do_intrinsic(_putCharRelease, jdk_internal_misc_Unsafe, putCharRelease_name, putChar_signature, F_R) \ - do_intrinsic(_putIntRelease, jdk_internal_misc_Unsafe, putIntRelease_name, putInt_signature, F_R) \ - do_intrinsic(_putLongRelease, jdk_internal_misc_Unsafe, putLongRelease_name, putLong_signature, F_R) \ - do_intrinsic(_putFloatRelease, jdk_internal_misc_Unsafe, putFloatRelease_name, putFloat_signature, F_R) \ - do_intrinsic(_putDoubleRelease, jdk_internal_misc_Unsafe, putDoubleRelease_name, putDouble_signature, F_R) \ - \ - do_name(getShortUnaligned_name,"getShortUnaligned") do_name(putShortUnaligned_name,"putShortUnaligned") \ - do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \ - do_name(getIntUnaligned_name,"getIntUnaligned") do_name(putIntUnaligned_name,"putIntUnaligned") \ - do_name(getLongUnaligned_name,"getLongUnaligned") do_name(putLongUnaligned_name,"putLongUnaligned") \ - \ - do_intrinsic(_getShortUnaligned, jdk_internal_misc_Unsafe, getShortUnaligned_name, getShort_signature, F_R) \ - do_intrinsic(_getCharUnaligned, jdk_internal_misc_Unsafe, getCharUnaligned_name, getChar_signature, F_R) \ - do_intrinsic(_getIntUnaligned, jdk_internal_misc_Unsafe, getIntUnaligned_name, getInt_signature, F_R) \ - do_intrinsic(_getLongUnaligned, jdk_internal_misc_Unsafe, getLongUnaligned_name, getLong_signature, F_R) \ - do_intrinsic(_putShortUnaligned, jdk_internal_misc_Unsafe, putShortUnaligned_name, putShort_signature, F_R) \ - do_intrinsic(_putCharUnaligned, jdk_internal_misc_Unsafe, putCharUnaligned_name, putChar_signature, F_R) \ - do_intrinsic(_putIntUnaligned, jdk_internal_misc_Unsafe, putIntUnaligned_name, putInt_signature, F_R) \ - do_intrinsic(_putLongUnaligned, jdk_internal_misc_Unsafe, putLongUnaligned_name, putLong_signature, F_R) \ - \ - do_signature(compareAndSetReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ - do_signature(compareAndExchangeReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \ - do_signature(compareAndSetLong_signature, "(Ljava/lang/Object;JJJ)Z") \ - do_signature(compareAndExchangeLong_signature, "(Ljava/lang/Object;JJJ)J") \ - do_signature(compareAndSetInt_signature, "(Ljava/lang/Object;JII)Z") \ - do_signature(compareAndExchangeInt_signature, "(Ljava/lang/Object;JII)I") \ - do_signature(compareAndSetByte_signature, "(Ljava/lang/Object;JBB)Z") \ - do_signature(compareAndExchangeByte_signature, "(Ljava/lang/Object;JBB)B") \ - do_signature(compareAndSetShort_signature, "(Ljava/lang/Object;JSS)Z") \ - do_signature(compareAndExchangeShort_signature, "(Ljava/lang/Object;JSS)S") \ - \ - do_name(compareAndSetReference_name, "compareAndSetReference") \ - do_name(compareAndExchangeReference_name, "compareAndExchangeReference") \ - do_name(compareAndExchangeReferenceAcquire_name, "compareAndExchangeReferenceAcquire") \ - do_name(compareAndExchangeReferenceRelease_name, "compareAndExchangeReferenceRelease") \ - do_name(compareAndSetLong_name, "compareAndSetLong") \ - do_name(compareAndExchangeLong_name, "compareAndExchangeLong") \ - do_name(compareAndExchangeLongAcquire_name, "compareAndExchangeLongAcquire") \ - do_name(compareAndExchangeLongRelease_name, "compareAndExchangeLongRelease") \ - do_name(compareAndSetInt_name, "compareAndSetInt") \ - do_name(compareAndExchangeInt_name, "compareAndExchangeInt") \ - do_name(compareAndExchangeIntAcquire_name, "compareAndExchangeIntAcquire") \ - do_name(compareAndExchangeIntRelease_name, "compareAndExchangeIntRelease") \ - do_name(compareAndSetByte_name, "compareAndSetByte") \ - do_name(compareAndExchangeByte_name, "compareAndExchangeByte") \ - do_name(compareAndExchangeByteAcquire_name, "compareAndExchangeByteAcquire") \ - do_name(compareAndExchangeByteRelease_name, "compareAndExchangeByteRelease") \ - do_name(compareAndSetShort_name, "compareAndSetShort") \ - do_name(compareAndExchangeShort_name, "compareAndExchangeShort") \ - do_name(compareAndExchangeShortAcquire_name, "compareAndExchangeShortAcquire") \ - do_name(compareAndExchangeShortRelease_name, "compareAndExchangeShortRelease") \ - \ - do_name(weakCompareAndSetReferencePlain_name, "weakCompareAndSetReferencePlain") \ - do_name(weakCompareAndSetReferenceAcquire_name, "weakCompareAndSetReferenceAcquire") \ - do_name(weakCompareAndSetReferenceRelease_name, "weakCompareAndSetReferenceRelease") \ - do_name(weakCompareAndSetReference_name, "weakCompareAndSetReference") \ - do_name(weakCompareAndSetLongPlain_name, "weakCompareAndSetLongPlain") \ - do_name(weakCompareAndSetLongAcquire_name, "weakCompareAndSetLongAcquire") \ - do_name(weakCompareAndSetLongRelease_name, "weakCompareAndSetLongRelease") \ - do_name(weakCompareAndSetLong_name, "weakCompareAndSetLong") \ - do_name(weakCompareAndSetIntPlain_name, "weakCompareAndSetIntPlain") \ - do_name(weakCompareAndSetIntAcquire_name, "weakCompareAndSetIntAcquire") \ - do_name(weakCompareAndSetIntRelease_name, "weakCompareAndSetIntRelease") \ - do_name(weakCompareAndSetInt_name, "weakCompareAndSetInt") \ - do_name(weakCompareAndSetBytePlain_name, "weakCompareAndSetBytePlain") \ - do_name(weakCompareAndSetByteAcquire_name, "weakCompareAndSetByteAcquire") \ - do_name(weakCompareAndSetByteRelease_name, "weakCompareAndSetByteRelease") \ - do_name(weakCompareAndSetByte_name, "weakCompareAndSetByte") \ - do_name(weakCompareAndSetShortPlain_name, "weakCompareAndSetShortPlain") \ - do_name(weakCompareAndSetShortAcquire_name, "weakCompareAndSetShortAcquire") \ - do_name(weakCompareAndSetShortRelease_name, "weakCompareAndSetShortRelease") \ - do_name(weakCompareAndSetShort_name, "weakCompareAndSetShort") \ - \ - do_intrinsic(_compareAndSetReference, jdk_internal_misc_Unsafe, compareAndSetReference_name, compareAndSetReference_signature, F_RN) \ - do_intrinsic(_compareAndExchangeReference, jdk_internal_misc_Unsafe, compareAndExchangeReference_name, compareAndExchangeReference_signature, F_RN) \ - do_intrinsic(_compareAndExchangeReferenceAcquire, jdk_internal_misc_Unsafe, compareAndExchangeReferenceAcquire_name, compareAndExchangeReference_signature, F_R) \ - do_intrinsic(_compareAndExchangeReferenceRelease, jdk_internal_misc_Unsafe, compareAndExchangeReferenceRelease_name, compareAndExchangeReference_signature, F_R) \ - do_intrinsic(_compareAndSetLong, jdk_internal_misc_Unsafe, compareAndSetLong_name, compareAndSetLong_signature, F_RN) \ - do_intrinsic(_compareAndExchangeLong, jdk_internal_misc_Unsafe, compareAndExchangeLong_name, compareAndExchangeLong_signature, F_RN) \ - do_intrinsic(_compareAndExchangeLongAcquire, jdk_internal_misc_Unsafe, compareAndExchangeLongAcquire_name, compareAndExchangeLong_signature, F_R) \ - do_intrinsic(_compareAndExchangeLongRelease, jdk_internal_misc_Unsafe, compareAndExchangeLongRelease_name, compareAndExchangeLong_signature, F_R) \ - do_intrinsic(_compareAndSetInt, jdk_internal_misc_Unsafe, compareAndSetInt_name, compareAndSetInt_signature, F_RN) \ - do_intrinsic(_compareAndExchangeInt, jdk_internal_misc_Unsafe, compareAndExchangeInt_name, compareAndExchangeInt_signature, F_RN) \ - do_intrinsic(_compareAndExchangeIntAcquire, jdk_internal_misc_Unsafe, compareAndExchangeIntAcquire_name, compareAndExchangeInt_signature, F_R) \ - do_intrinsic(_compareAndExchangeIntRelease, jdk_internal_misc_Unsafe, compareAndExchangeIntRelease_name, compareAndExchangeInt_signature, F_R) \ - do_intrinsic(_compareAndSetByte, jdk_internal_misc_Unsafe, compareAndSetByte_name, compareAndSetByte_signature, F_R) \ - do_intrinsic(_compareAndExchangeByte, jdk_internal_misc_Unsafe, compareAndExchangeByte_name, compareAndExchangeByte_signature, F_R) \ - do_intrinsic(_compareAndExchangeByteAcquire, jdk_internal_misc_Unsafe, compareAndExchangeByteAcquire_name, compareAndExchangeByte_signature, F_R) \ - do_intrinsic(_compareAndExchangeByteRelease, jdk_internal_misc_Unsafe, compareAndExchangeByteRelease_name, compareAndExchangeByte_signature, F_R) \ - do_intrinsic(_compareAndSetShort, jdk_internal_misc_Unsafe, compareAndSetShort_name, compareAndSetShort_signature, F_R) \ - do_intrinsic(_compareAndExchangeShort, jdk_internal_misc_Unsafe, compareAndExchangeShort_name, compareAndExchangeShort_signature, F_R) \ - do_intrinsic(_compareAndExchangeShortAcquire, jdk_internal_misc_Unsafe, compareAndExchangeShortAcquire_name, compareAndExchangeShort_signature, F_R) \ - do_intrinsic(_compareAndExchangeShortRelease, jdk_internal_misc_Unsafe, compareAndExchangeShortRelease_name, compareAndExchangeShort_signature, F_R) \ - \ - do_intrinsic(_weakCompareAndSetReferencePlain, jdk_internal_misc_Unsafe, weakCompareAndSetReferencePlain_name, compareAndSetReference_signature, F_R) \ - do_intrinsic(_weakCompareAndSetReferenceAcquire,jdk_internal_misc_Unsafe, weakCompareAndSetReferenceAcquire_name, compareAndSetReference_signature, F_R) \ - do_intrinsic(_weakCompareAndSetReferenceRelease,jdk_internal_misc_Unsafe, weakCompareAndSetReferenceRelease_name, compareAndSetReference_signature, F_R) \ - do_intrinsic(_weakCompareAndSetReference, jdk_internal_misc_Unsafe, weakCompareAndSetReference_name, compareAndSetReference_signature, F_R) \ - do_intrinsic(_weakCompareAndSetLongPlain, jdk_internal_misc_Unsafe, weakCompareAndSetLongPlain_name, compareAndSetLong_signature, F_R) \ - do_intrinsic(_weakCompareAndSetLongAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetLongAcquire_name, compareAndSetLong_signature, F_R) \ - do_intrinsic(_weakCompareAndSetLongRelease, jdk_internal_misc_Unsafe, weakCompareAndSetLongRelease_name, compareAndSetLong_signature, F_R) \ - do_intrinsic(_weakCompareAndSetLong, jdk_internal_misc_Unsafe, weakCompareAndSetLong_name, compareAndSetLong_signature, F_R) \ - do_intrinsic(_weakCompareAndSetIntPlain, jdk_internal_misc_Unsafe, weakCompareAndSetIntPlain_name, compareAndSetInt_signature, F_R) \ - do_intrinsic(_weakCompareAndSetIntAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetIntAcquire_name, compareAndSetInt_signature, F_R) \ - do_intrinsic(_weakCompareAndSetIntRelease, jdk_internal_misc_Unsafe, weakCompareAndSetIntRelease_name, compareAndSetInt_signature, F_R) \ - do_intrinsic(_weakCompareAndSetInt, jdk_internal_misc_Unsafe, weakCompareAndSetInt_name, compareAndSetInt_signature, F_R) \ - do_intrinsic(_weakCompareAndSetBytePlain, jdk_internal_misc_Unsafe, weakCompareAndSetBytePlain_name, compareAndSetByte_signature, F_R) \ - do_intrinsic(_weakCompareAndSetByteAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetByteAcquire_name, compareAndSetByte_signature, F_R) \ - do_intrinsic(_weakCompareAndSetByteRelease, jdk_internal_misc_Unsafe, weakCompareAndSetByteRelease_name, compareAndSetByte_signature, F_R) \ - do_intrinsic(_weakCompareAndSetByte, jdk_internal_misc_Unsafe, weakCompareAndSetByte_name, compareAndSetByte_signature, F_R) \ - do_intrinsic(_weakCompareAndSetShortPlain, jdk_internal_misc_Unsafe, weakCompareAndSetShortPlain_name, compareAndSetShort_signature, F_R) \ - do_intrinsic(_weakCompareAndSetShortAcquire, jdk_internal_misc_Unsafe, weakCompareAndSetShortAcquire_name, compareAndSetShort_signature, F_R) \ - do_intrinsic(_weakCompareAndSetShortRelease, jdk_internal_misc_Unsafe, weakCompareAndSetShortRelease_name, compareAndSetShort_signature, F_R) \ - do_intrinsic(_weakCompareAndSetShort, jdk_internal_misc_Unsafe, weakCompareAndSetShort_name, compareAndSetShort_signature, F_R) \ - \ - do_intrinsic(_getAndAddInt, jdk_internal_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \ - do_name( getAndAddInt_name, "getAndAddInt") \ - do_signature(getAndAddInt_signature, "(Ljava/lang/Object;JI)I" ) \ - do_intrinsic(_getAndAddLong, jdk_internal_misc_Unsafe, getAndAddLong_name, getAndAddLong_signature, F_R) \ - do_name( getAndAddLong_name, "getAndAddLong") \ - do_signature(getAndAddLong_signature, "(Ljava/lang/Object;JJ)J" ) \ - do_intrinsic(_getAndAddByte, jdk_internal_misc_Unsafe, getAndAddByte_name, getAndAddByte_signature, F_R) \ - do_name( getAndAddByte_name, "getAndAddByte") \ - do_signature(getAndAddByte_signature, "(Ljava/lang/Object;JB)B" ) \ - do_intrinsic(_getAndAddShort, jdk_internal_misc_Unsafe, getAndAddShort_name, getAndAddShort_signature, F_R) \ - do_name( getAndAddShort_name, "getAndAddShort") \ - do_signature(getAndAddShort_signature, "(Ljava/lang/Object;JS)S" ) \ - do_intrinsic(_getAndSetInt, jdk_internal_misc_Unsafe, getAndSetInt_name, getAndSetInt_signature, F_R) \ - do_name( getAndSetInt_name, "getAndSetInt") \ - do_alias( getAndSetInt_signature, /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature) \ - do_intrinsic(_getAndSetLong, jdk_internal_misc_Unsafe, getAndSetLong_name, getAndSetLong_signature, F_R) \ - do_name( getAndSetLong_name, "getAndSetLong") \ - do_alias( getAndSetLong_signature, /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature) \ - do_intrinsic(_getAndSetByte, jdk_internal_misc_Unsafe, getAndSetByte_name, getAndSetByte_signature, F_R) \ - do_name( getAndSetByte_name, "getAndSetByte") \ - do_alias( getAndSetByte_signature, /*"(Ljava/lang/Object;JB)B"*/ getAndAddByte_signature) \ - do_intrinsic(_getAndSetShort, jdk_internal_misc_Unsafe, getAndSetShort_name, getAndSetShort_signature, F_R) \ - do_name( getAndSetShort_name, "getAndSetShort") \ - do_alias( getAndSetShort_signature, /*"(Ljava/lang/Object;JS)S"*/ getAndAddShort_signature) \ - do_intrinsic(_getAndSetReference, jdk_internal_misc_Unsafe, getAndSetReference_name, getAndSetReference_signature, F_R) \ - do_name( getAndSetReference_name, "getAndSetReference") \ - do_signature(getAndSetReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \ - \ - /* (2) Bytecode intrinsics */ \ - \ - do_intrinsic(_park, jdk_internal_misc_Unsafe, park_name, park_signature, F_R) \ - do_name( park_name, "park") \ - do_signature(park_signature, "(ZJ)V") \ - do_intrinsic(_unpark, jdk_internal_misc_Unsafe, unpark_name, unpark_signature, F_R) \ - do_name( unpark_name, "unpark") \ - do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \ - \ - do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \ - do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \ - do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \ - \ - do_intrinsic(_StringBuilder_append_char, java_lang_StringBuilder, append_name, char_StringBuilder_signature, F_R) \ - do_intrinsic(_StringBuilder_append_int, java_lang_StringBuilder, append_name, int_StringBuilder_signature, F_R) \ - do_intrinsic(_StringBuilder_append_String, java_lang_StringBuilder, append_name, String_StringBuilder_signature, F_R) \ - \ - do_intrinsic(_StringBuilder_toString, java_lang_StringBuilder, toString_name, void_string_signature, F_R) \ - \ - do_intrinsic(_StringBuffer_void, java_lang_StringBuffer, object_initializer_name, void_method_signature, F_R) \ - do_intrinsic(_StringBuffer_int, java_lang_StringBuffer, object_initializer_name, int_void_signature, F_R) \ - do_intrinsic(_StringBuffer_String, java_lang_StringBuffer, object_initializer_name, string_void_signature, F_R) \ - \ - do_intrinsic(_StringBuffer_append_char, java_lang_StringBuffer, append_name, char_StringBuffer_signature, F_Y) \ - do_intrinsic(_StringBuffer_append_int, java_lang_StringBuffer, append_name, int_StringBuffer_signature, F_Y) \ - do_intrinsic(_StringBuffer_append_String, java_lang_StringBuffer, append_name, String_StringBuffer_signature, F_Y) \ - \ - do_intrinsic(_StringBuffer_toString, java_lang_StringBuffer, toString_name, void_string_signature, F_Y) \ - \ - do_intrinsic(_Integer_toString, java_lang_Integer, toString_name, int_String_signature, F_S) \ - \ - do_intrinsic(_String_String, java_lang_String, object_initializer_name, string_void_signature, F_R) \ - \ - do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ - /* (symbol object_initializer_name defined above) */ \ - \ - do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_object_array_object_signature, F_R) \ - /* (symbols invoke_name and invoke_signature defined above) */ \ - /* the polymorphic MH intrinsics must be in compact order, with _invokeGeneric first and _linkToInterface last */ \ - do_intrinsic(_invokeGeneric, java_lang_invoke_MethodHandle, invoke_name, star_name, F_RN) \ - do_intrinsic(_invokeBasic, java_lang_invoke_MethodHandle, invokeBasic_name, star_name, F_RN) \ - do_intrinsic(_linkToVirtual, java_lang_invoke_MethodHandle, linkToVirtual_name, star_name, F_SN) \ - do_intrinsic(_linkToStatic, java_lang_invoke_MethodHandle, linkToStatic_name, star_name, F_SN) \ - do_intrinsic(_linkToSpecial, java_lang_invoke_MethodHandle, linkToSpecial_name, star_name, F_SN) \ - do_intrinsic(_linkToInterface, java_lang_invoke_MethodHandle, linkToInterface_name, star_name, F_SN) \ - /* special marker for bytecode generated for the JVM from a LambdaForm: */ \ - do_intrinsic(_compiledLambdaForm, java_lang_invoke_MethodHandle, compiledLambdaForm_name, star_name, F_RN) \ - \ - /* unboxing methods: */ \ - do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ - do_name( booleanValue_name, "booleanValue") \ - do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \ - do_name( byteValue_name, "byteValue") \ - do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \ - do_name( charValue_name, "charValue") \ - do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \ - do_name( shortValue_name, "shortValue") \ - do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \ - do_name( intValue_name, "intValue") \ - do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \ - do_name( longValue_name, "longValue") \ - do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \ - do_name( floatValue_name, "floatValue") \ - do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \ - do_name( doubleValue_name, "doubleValue") \ - \ - /* boxing methods: */ \ - do_name( valueOf_name, "valueOf") \ - do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \ - do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \ - do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \ - do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \ - do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \ - do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \ - do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \ - do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \ - do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \ - do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \ - do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \ - do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \ - do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \ - do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \ - do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \ - do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \ - \ - /* forEachRemaining */ \ - do_intrinsic(_forEachRemaining, java_util_stream_StreamsRangeIntSpliterator, forEachRemaining_name, forEachRemaining_signature, F_R) \ - do_name( forEachRemaining_name, "forEachRemaining") \ - do_name( forEachRemaining_signature, "(Ljava/util/function/IntConsumer;)V") \ - - /*end*/ - - // Class vmSymbols diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index b9a63dbd97f..3b589844232 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -49,6 +49,7 @@ #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/deoptimization.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/icache.hpp" #include "runtime/java.hpp" diff --git a/src/hotspot/share/code/debugInfoRec.cpp b/src/hotspot/share/code/debugInfoRec.cpp index a6f2dbbb971..b19b9defc4d 100644 --- a/src/hotspot/share/code/debugInfoRec.cpp +++ b/src/hotspot/share/code/debugInfoRec.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * 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,6 +26,7 @@ #include "code/debugInfoRec.hpp" #include "code/scopeDesc.hpp" #include "prims/jvmtiExport.hpp" +#include "runtime/globals_extension.hpp" // Private definition. // There is one DIR_Chunk for each scope and values array. diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp index ff1956d5c5d..cbf591eb638 100644 --- a/src/hotspot/share/code/dependencies.cpp +++ b/src/hotspot/share/code/dependencies.cpp @@ -41,16 +41,18 @@ #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/vmThread.hpp" #include "utilities/copy.hpp" #ifdef ASSERT static bool must_be_in_vm() { Thread* thread = Thread::current(); - if (thread->is_Java_thread()) - return ((JavaThread*)thread)->thread_state() == _thread_in_vm; - else - return true; //something like this: thread->is_VM_thread(); + if (thread->is_Java_thread()) { + return thread->as_Java_thread()->thread_state() == _thread_in_vm; + } else { + return true; // Could be VMThread or GC thread + } } #endif //ASSERT diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index b5ce247f917..14c0024cfcf 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -36,6 +36,7 @@ #include "oops/oop.inline.hpp" #include "prims/nativeLookup.hpp" #include "runtime/frame.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.hpp" diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 50521eb1129..9beb34192f9 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -50,6 +50,7 @@ #include "prims/whitebox.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.inline.hpp" @@ -249,11 +250,6 @@ bool compileBroker_init() { CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { CompilerThread* thread = CompilerThread::current(); thread->set_task(task); -#if INCLUDE_JVMCI - if (task->is_blocking() && CompileBroker::compiler(task->comp_level())->is_jvmci()) { - task->set_jvmci_compiler_thread(thread); - } -#endif CompileLog* log = thread->log(); if (log != NULL && !task->is_unloaded()) task->log_task_start(log); } @@ -277,7 +273,7 @@ CompileTaskWrapper::~CompileTaskWrapper() { // The waiting thread timed out and thus did not free the task. free_task = true; } - task->set_jvmci_compiler_thread(NULL); + task->set_blocking_jvmci_compile_state(NULL); } #endif if (!free_task) { @@ -606,19 +602,16 @@ void register_jfr_phasetype_serializer(CompilerType compiler_type) { ResourceMark rm; static bool first_registration = true; if (compiler_type == compiler_jvmci) { - // register serializer, phases will be added later lazily. - GrowableArray<const char*>* jvmci_phase_names = new GrowableArray<const char*>(1); - jvmci_phase_names->append("NOT_A_PHASE_NAME"); - CompilerEvent::PhaseEvent::register_phases(jvmci_phase_names); + CompilerEvent::PhaseEvent::get_phase_id("NOT_A_PHASE_NAME", false, false, false); first_registration = false; #ifdef COMPILER2 } else if (compiler_type == compiler_c2) { assert(first_registration, "invariant"); // c2 must be registered first. GrowableArray<const char*>* c2_phase_names = new GrowableArray<const char*>(PHASE_NUM_TYPES); for (int i = 0; i < PHASE_NUM_TYPES; i++) { - c2_phase_names->append(CompilerPhaseTypeHelper::to_string((CompilerPhaseType)i)); + const char* phase_name = CompilerPhaseTypeHelper::to_string((CompilerPhaseType) i); + CompilerEvent::PhaseEvent::get_phase_id(phase_name, false, false, false); } - CompilerEvent::PhaseEvent::register_phases(c2_phase_names); first_registration = false; #endif // COMPILER2 } @@ -1183,7 +1176,7 @@ void CompileBroker::compile_method_base(const methodHandle& method, if (!UseJVMCINativeLibrary) { // Don't allow blocking compiles if inside a class initializer or while performing class loading - vframeStream vfst((JavaThread*) thread); + vframeStream vfst(thread->as_Java_thread()); for (; !vfst.at_end(); vfst.next()) { if (vfst.method()->is_static_initializer() || (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) && @@ -1604,22 +1597,27 @@ bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask* assert(UseJVMCICompiler, "sanity"); MonitorLocker ml(thread, task->lock()); int progress_wait_attempts = 0; - int methods_compiled = jvmci->methods_compiled(); + jint thread_jvmci_compilation_ticks = 0; + jint global_jvmci_compilation_ticks = jvmci->global_compilation_ticks(); while (!task->is_complete() && !is_compilation_disabled_forever() && ml.wait(JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) { - CompilerThread* jvmci_compiler_thread = task->jvmci_compiler_thread(); + JVMCICompileState* jvmci_compile_state = task->blocking_jvmci_compile_state(); bool progress; - if (jvmci_compiler_thread != NULL) { - // If the JVMCI compiler thread is not blocked or suspended, we deem it to be making progress. - progress = jvmci_compiler_thread->thread_state() != _thread_blocked && - !jvmci_compiler_thread->is_external_suspend(); + if (jvmci_compile_state != NULL) { + jint ticks = jvmci_compile_state->compilation_ticks(); + progress = (ticks - thread_jvmci_compilation_ticks) != 0; + JVMCI_event_1("waiting on compilation %d [ticks=%d]", task->compile_id(), ticks); + thread_jvmci_compilation_ticks = ticks; } else { // Still waiting on JVMCI compiler queue. This thread may be holding a lock - // that all JVMCI compiler threads are blocked on. We use the counter for - // successful JVMCI compilations to determine whether JVMCI compilation + // that all JVMCI compiler threads are blocked on. We use the global JVMCI + // compilation ticks to determine whether JVMCI compilation // is still making progress through the JVMCI compiler queue. - progress = jvmci->methods_compiled() != methods_compiled; + jint ticks = jvmci->global_compilation_ticks(); + progress = (ticks - global_jvmci_compilation_ticks) != 0; + JVMCI_event_1("waiting on compilation %d to be queued [ticks=%d]", task->compile_id(), ticks); + global_jvmci_compilation_ticks = ticks; } if (!progress) { @@ -1627,13 +1625,11 @@ bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask* if (PrintCompilation) { task->print(tty, "wait for blocking compilation timed out"); } + JVMCI_event_1("waiting on compilation %d timed out", task->compile_id()); break; } } else { progress_wait_attempts = 0; - if (jvmci_compiler_thread == NULL) { - methods_compiled = jvmci->methods_compiled(); - } } } task->clear_waiter(); @@ -2152,7 +2148,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { TraceTime t1("compilation", &time); EventCompilation event; - JVMCICompileState compile_state(task); + JVMCICompileState compile_state(task, jvmci); JVMCIRuntime *runtime = NULL; if (JVMCI::in_shutdown()) { diff --git a/src/hotspot/share/compiler/compileTask.cpp b/src/hotspot/share/compiler/compileTask.cpp index 26155b19f13..e4147062fb7 100644 --- a/src/hotspot/share/compiler/compileTask.cpp +++ b/src/hotspot/share/compiler/compileTask.cpp @@ -100,7 +100,7 @@ void CompileTask::initialize(int compile_id, _osr_bci = osr_bci; _is_blocking = is_blocking; JVMCI_ONLY(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();) - JVMCI_ONLY(_jvmci_compiler_thread = NULL;) + JVMCI_ONLY(_blocking_jvmci_compile_state = NULL;) _comp_level = comp_level; _num_inlined_bytecodes = 0; diff --git a/src/hotspot/share/compiler/compileTask.hpp b/src/hotspot/share/compiler/compileTask.hpp index fd8c4603329..03beb350b1b 100644 --- a/src/hotspot/share/compiler/compileTask.hpp +++ b/src/hotspot/share/compiler/compileTask.hpp @@ -31,6 +31,8 @@ #include "memory/allocation.hpp" #include "utilities/xmlstream.hpp" +JVMCI_ONLY(class JVMCICompileState;) + // CompileTask // // An entry in the compile queue. It represents a pending or current @@ -81,8 +83,8 @@ class CompileTask : public CHeapObj<mtCompiler> { bool _is_blocking; #if INCLUDE_JVMCI bool _has_waiter; - // Compiler thread for a blocking JVMCI compilation - CompilerThread* _jvmci_compiler_thread; + // Compilation state for a blocking JVMCI compilation + JVMCICompileState* _blocking_jvmci_compile_state; #endif int _comp_level; int _num_inlined_bytecodes; @@ -144,11 +146,9 @@ class CompileTask : public CHeapObj<mtCompiler> { bool has_waiter() const { return _has_waiter; } void clear_waiter() { _has_waiter = false; } - CompilerThread* jvmci_compiler_thread() const { return _jvmci_compiler_thread; } - void set_jvmci_compiler_thread(CompilerThread* t) { - assert(is_blocking(), "must be"); - assert((t == NULL) != (_jvmci_compiler_thread == NULL), "must be"); - _jvmci_compiler_thread = t; + JVMCICompileState* blocking_jvmci_compile_state() const { return _blocking_jvmci_compile_state; } + void set_blocking_jvmci_compile_state(JVMCICompileState* state) { + _blocking_jvmci_compile_state = state; } #endif diff --git a/src/hotspot/share/compiler/compilerEvent.cpp b/src/hotspot/share/compiler/compilerEvent.cpp index 5aca2de2856..f89db6ce389 100644 --- a/src/hotspot/share/compiler/compilerEvent.cpp +++ b/src/hotspot/share/compiler/compilerEvent.cpp @@ -34,67 +34,84 @@ class PhaseTypeGuard : public StackObj { private: static Semaphore _mutex_semaphore; + bool _enabled; public: - PhaseTypeGuard() { - _mutex_semaphore.wait(); + PhaseTypeGuard(bool enabled=true) { + if (enabled) { + _mutex_semaphore.wait(); + _enabled = true; + } else { + _enabled = false; + } } ~PhaseTypeGuard() { - _mutex_semaphore.signal(); + if (_enabled) { + _mutex_semaphore.signal(); + } } }; Semaphore PhaseTypeGuard::_mutex_semaphore(1); -static void write_phases(JfrCheckpointWriter& writer, u4 base_idx, GrowableArray<const char*>* phases) { - assert(phases != NULL, "invariant"); - assert(phases->is_nonempty(), "invariant"); - const u4 nof_entries = phases->length(); - writer.write_count(nof_entries); - for (u4 i = 0; i < nof_entries; i++) { - writer.write_key(base_idx + i); - writer.write(phases->at(i)); - } -} - +// Table for mapping compiler phases names to int identifiers. static GrowableArray<const char*>* phase_names = NULL; class CompilerPhaseTypeConstant : public JfrSerializer { public: void serialize(JfrCheckpointWriter& writer) { PhaseTypeGuard guard; - write_phases(writer, 0, phase_names); + assert(phase_names != NULL, "invariant"); + assert(phase_names->is_nonempty(), "invariant"); + const u4 nof_entries = phase_names->length(); + writer.write_count(nof_entries); + for (u4 i = 0; i < nof_entries; i++) { + writer.write_key(i); + writer.write(phase_names->at(i)); + } } }; -// This function provides support for adding dynamic entries to JFR type CompilerPhaseType. -// The mapping for CompilerPhaseType is maintained as growable array phase_names. -// The serializer CompilerPhaseTypeConstant must be registered with JFR at vm init. -// Registration of new phase names creates mapping, serialize it for current chunk and registers its serializer with JFR if it is not already done. -int CompilerEvent::PhaseEvent::register_phases(GrowableArray<const char*>* new_phases) { - int idx = -1; - if (new_phases == NULL || new_phases->is_empty()) { - return idx; +static int lookup_phase(const char* phase_name) { + for (int i = 0; i < phase_names->length(); i++) { + const char* name = phase_names->at(i); + if (strcmp(name, phase_name) == 0) { + return i; + } } + return -1; +} + +int CompilerEvent::PhaseEvent::get_phase_id(const char* phase_name, bool may_exist, bool use_strdup, bool sync) { + int index; bool register_jfr_serializer = false; { - PhaseTypeGuard guard; + PhaseTypeGuard guard(sync); if (phase_names == NULL) { - phase_names = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<const char*>(100, mtCompiler); + phase_names = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<const char*>(100, mtCompiler); register_jfr_serializer = true; + } else if (may_exist) { + index = lookup_phase(phase_name); + if (index != -1) { + return index; + } + } else { + assert((index = lookup_phase(phase_name)) == -1, "phase name \"%s\" already registered: %d", phase_name, index); } - idx = phase_names->length(); - phase_names->appendAll(new_phases); - guarantee(phase_names->length() < 256, "exceeds maximum supported phases"); + + index = phase_names->length(); + phase_names->append(use_strdup ? strdup(phase_name) : phase_name); } if (register_jfr_serializer) { JfrSerializer::register_serializer(TYPE_COMPILERPHASETYPE, false, new CompilerPhaseTypeConstant()); } else if (Jfr::is_recording()) { - // serialize new_phases. + // serialize new phase. JfrCheckpointWriter writer; writer.write_type(TYPE_COMPILERPHASETYPE); - write_phases(writer, idx, new_phases); + writer.write_count(1); + writer.write_key(index); + writer.write(phase_name); } - return idx; + return index; } void CompilerEvent::CompilationEvent::post(EventCompilation& event, int compile_id, CompilerType compiler_type, Method* method, int compile_level, bool success, bool is_osr, int code_size, int inlined_bytecodes) { diff --git a/src/hotspot/share/compiler/compilerEvent.hpp b/src/hotspot/share/compiler/compilerEvent.hpp index ae94d4cf185..65fc296b66b 100644 --- a/src/hotspot/share/compiler/compilerEvent.hpp +++ b/src/hotspot/share/compiler/compilerEvent.hpp @@ -64,15 +64,13 @@ class CompilerEvent : AllStatic { class PhaseEvent : AllStatic { friend class CompilerPhaseTypeConstant; public: - /** - * Register compiler phases for JFR type CompilerPhaseType serialization purposes. - * This method is called during compiler creation or during compilation. - * Registration will serialize the passed in phase constants, supporting bulk and/or incremental registrations. - * This method returns start index of new list that just got appended to phase_names. - * Param new_phases may contain duplicates. - * Return value could be used for mapping purpose at caller site, or caller can assume explicit order of registration. - */ - static int register_phases(GrowableArray<const char*>* new_phases) NOT_JFR_RETURN_(-1); + + // Gets a unique identifier for `phase_name`, computing and registering it first if necessary. + // If `may_exist` is true, then current registrations are searched first. If false, then + // there must not be an existing registration for `phase_name`. + // If `use_strdup` is true, then `phase_name` is strdup'ed before registration. + // If `sync` is true, then access to the registration table is synchronized. + static int get_phase_id(const char* phase_name, bool may_exist, bool use_strdup, bool sync) NOT_JFR_RETURN_(-1); static void post(EventCompilerPhase& event, const Ticks& start_time, int phase, int compile_id, int level) NOT_JFR_RETURN(); static void post(EventCompilerPhase& event, jlong start_time, int phase, int compile_id, int level) { diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index fe4c93d450c..26328783964 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * 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 @@ #include "oops/klass.hpp" #include "oops/method.hpp" #include "oops/symbol.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/share/compiler/tieredThresholdPolicy.cpp b/src/hotspot/share/compiler/tieredThresholdPolicy.cpp index a380e90e49d..5f062650f25 100644 --- a/src/hotspot/share/compiler/tieredThresholdPolicy.cpp +++ b/src/hotspot/share/compiler/tieredThresholdPolicy.cpp @@ -29,6 +29,7 @@ #include "memory/resourceArea.hpp" #include "runtime/arguments.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/safepoint.hpp" #include "runtime/safepointVerifiers.hpp" diff --git a/src/hotspot/share/gc/epsilon/epsilonArguments.cpp b/src/hotspot/share/gc/epsilon/epsilonArguments.cpp index 52652ed687c..17cac8d86bf 100644 --- a/src/hotspot/share/gc/epsilon/epsilonArguments.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonArguments.cpp @@ -28,7 +28,6 @@ #include "gc/shared/gcArguments.hpp" #include "runtime/globals.hpp" #include "runtime/globals_extension.hpp" -#include "runtime/vm_version.hpp" #include "utilities/macros.hpp" size_t EpsilonArguments::conservative_max_heap_alignment() { diff --git a/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp index da48b3f1ec5..b039a949dcf 100644 --- a/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp @@ -41,7 +41,7 @@ EpsilonBarrierSet::EpsilonBarrierSet() : BarrierSet( make_barrier_set_c1<BarrierSetC1>(), make_barrier_set_c2<BarrierSetC2>(), NULL /* barrier_set_nmethod */, - BarrierSet::FakeRtti(BarrierSet::EpsilonBarrierSet)) {}; + BarrierSet::FakeRtti(BarrierSet::EpsilonBarrierSet)) {} void EpsilonBarrierSet::on_thread_create(Thread *thread) { EpsilonThreadLocalData::create(thread); diff --git a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp index 78d08a4dd5a..7e77026ac5a 100644 --- a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp @@ -46,7 +46,6 @@ jint EpsilonHeap::initialize() { _virtual_space.initialize(heap_rs, init_byte_size); MemRegion committed_region((HeapWord*)_virtual_space.low(), (HeapWord*)_virtual_space.high()); - MemRegion reserved_region((HeapWord*)_virtual_space.low_boundary(), (HeapWord*)_virtual_space.high_boundary()); initialize_reserved_region(heap_rs); diff --git a/src/hotspot/share/gc/epsilon/epsilonInitLogger.cpp b/src/hotspot/share/gc/epsilon/epsilonInitLogger.cpp index c18bc1d8206..1006e848b5d 100644 --- a/src/hotspot/share/gc/epsilon/epsilonInitLogger.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonInitLogger.cpp @@ -27,6 +27,7 @@ #include "gc/epsilon/epsilonInitLogger.hpp" #include "logging/log.hpp" #include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" #include "utilities/globalDefinitions.hpp" void EpsilonInitLogger::print_gc_specific() { diff --git a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp index 666cbfdebe7..6ced6ae55f7 100644 --- a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp @@ -27,7 +27,6 @@ #include "gc/epsilon/epsilonHeap.hpp" #include "gc/shared/generationCounters.hpp" #include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" #include "memory/metaspaceCounters.hpp" #include "memory/resourceArea.hpp" #include "services/memoryService.hpp" diff --git a/src/hotspot/share/gc/epsilon/epsilon_globals.hpp b/src/hotspot/share/gc/epsilon/epsilon_globals.hpp index 2387240bc1a..fbcb9c47aab 100644 --- a/src/hotspot/share/gc/epsilon/epsilon_globals.hpp +++ b/src/hotspot/share/gc/epsilon/epsilon_globals.hpp @@ -33,65 +33,61 @@ // #define GC_EPSILON_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ - notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ - range, \ - constraint) \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ \ - experimental(size_t, EpsilonPrintHeapSteps, 20, \ + product(size_t, EpsilonPrintHeapSteps, 20, EXPERIMENTAL, \ "Print heap occupancy stats with this number of steps. " \ "0 turns the printing off.") \ range(0, max_intx) \ \ - experimental(size_t, EpsilonUpdateCountersStep, 1 * M, \ + product(size_t, EpsilonUpdateCountersStep, 1 * M, EXPERIMENTAL, \ "Update heap occupancy counters after allocating this much " \ "memory. Higher values would make allocations faster at " \ "the expense of lower resolution in heap counters.") \ range(1, max_intx) \ \ - experimental(size_t, EpsilonMaxTLABSize, 4 * M, \ + product(size_t, EpsilonMaxTLABSize, 4 * M, EXPERIMENTAL, \ "Max TLAB size to use with Epsilon GC. Larger value improves " \ "performance at the expense of per-thread memory waste. This " \ "asks TLAB machinery to cap TLAB sizes at this value.") \ range(1, max_intx) \ \ - experimental(bool, EpsilonElasticTLAB, true, \ + product(bool, EpsilonElasticTLAB, true, EXPERIMENTAL, \ "Use elastic policy to manage TLAB sizes. This conserves memory " \ "for non-actively allocating threads, even when they request " \ "large TLABs for themselves. Active threads would experience " \ "smaller TLABs until policy catches up.") \ \ - experimental(bool, EpsilonElasticTLABDecay, true, \ + product(bool, EpsilonElasticTLABDecay, true, EXPERIMENTAL, \ "Use timed decays to shrik TLAB sizes. This conserves memory " \ "for the threads that allocate in bursts of different sizes, " \ "for example the small/rare allocations coming after the initial "\ "large burst.") \ \ - experimental(double, EpsilonTLABElasticity, 1.1, \ + product(double, EpsilonTLABElasticity, 1.1, EXPERIMENTAL, \ "Multiplier to use when deciding on next TLAB size. Larger value "\ "improves performance at the expense of per-thread memory waste. "\ "Lower value improves memory footprint, but penalizes actively " \ "allocating threads.") \ range(1.0, DBL_MAX) \ \ - experimental(size_t, EpsilonTLABDecayTime, 1000, \ + product(size_t, EpsilonTLABDecayTime, 1000, EXPERIMENTAL, \ "TLAB sizing policy decays to initial size after thread had not " \ "allocated for this long. Time is in milliseconds. Lower value " \ "improves memory footprint, but penalizes actively allocating " \ "threads.") \ range(1, max_intx) \ \ - experimental(size_t, EpsilonMinHeapExpand, 128 * M, \ + product(size_t, EpsilonMinHeapExpand, 128 * M, EXPERIMENTAL, \ "Min expansion step for heap. Larger value improves performance " \ "at the potential expense of memory waste.") \ range(1, max_intx) +// end of GC_EPSILON_FLAGS + #endif // SHARE_GC_EPSILON_EPSILON_GLOBALS_HPP diff --git a/src/hotspot/share/gc/g1/g1Analytics.cpp b/src/hotspot/share/gc/g1/g1Analytics.cpp index 853de98da24..966d017e786 100644 --- a/src/hotspot/share/gc/g1/g1Analytics.cpp +++ b/src/hotspot/share/gc/g1/g1Analytics.cpp @@ -151,7 +151,8 @@ void G1Analytics::report_alloc_rate_ms(double alloc_rate) { void G1Analytics::compute_pause_time_ratios(double end_time_sec, double pause_time_ms) { double long_interval_ms = (end_time_sec - oldest_known_gc_end_time_sec()) * 1000.0; - _long_term_pause_time_ratio = _recent_gc_times_ms->sum() / long_interval_ms; + double gc_pause_time_ms = _recent_gc_times_ms->sum() - _recent_gc_times_ms->oldest() + pause_time_ms; + _long_term_pause_time_ratio = gc_pause_time_ms / long_interval_ms; _long_term_pause_time_ratio = clamp(_long_term_pause_time_ratio, 0.0, 1.0); double short_interval_ms = (end_time_sec - most_recent_gc_end_time_sec()) * 1000.0; @@ -224,7 +225,11 @@ void G1Analytics::report_rs_length(double rs_length) { } double G1Analytics::predict_alloc_rate_ms() const { - return predict_zero_bounded(_alloc_rate_ms_seq); + if (enough_samples_available(_alloc_rate_ms_seq)) { + return predict_zero_bounded(_alloc_rate_ms_seq); + } else { + return 0.0; + } } double G1Analytics::predict_concurrent_refine_rate_ms() const { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index ab28e850a33..b09262048a8 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1677,21 +1677,21 @@ jint G1CollectedHeap::initialize() { // 6843694 - ensure that the maximum region index can fit // in the remembered set structures. const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; - guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); + guarantee((max_reserved_regions() - 1) <= max_region_idx, "too many regions"); // The G1FromCardCache reserves card with value 0 as "invalid", so the heap must not // start within the first card. guarantee(heap_rs.base() >= (char*)G1CardTable::card_size, "Java heap must not start within the first card."); // Also create a G1 rem set. _rem_set = new G1RemSet(this, _card_table, _hot_card_cache); - _rem_set->initialize(max_regions()); + _rem_set->initialize(max_reserved_regions()); size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized"); guarantee(HeapRegion::CardsPerRegion < max_cards_per_region, "too many cards per region"); - FreeRegionList::set_unrealistically_long_length(max_expandable_regions() + 1); + FreeRegionList::set_unrealistically_long_length(max_regions() + 1); _bot = new G1BlockOffsetTable(reserved(), bot_storage); @@ -1713,7 +1713,7 @@ jint G1CollectedHeap::initialize() { _numa->set_region_info(HeapRegion::GrainBytes, page_size); // Create the G1ConcurrentMark data structure and thread. - // (Must do this late, so that "max_regions" is defined.) + // (Must do this late, so that "max_[reserved_]regions" is defined.) _cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage); _cm_thread = _cm->cm_thread(); @@ -1765,7 +1765,7 @@ jint G1CollectedHeap::initialize() { _preserved_marks_set.init(ParallelGCThreads); - _collection_set.initialize(max_regions()); + _collection_set.initialize(max_reserved_regions()); G1InitLogger::print(); @@ -2391,7 +2391,7 @@ size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const { } size_t G1CollectedHeap::max_capacity() const { - return _hrm->max_expandable_length() * HeapRegion::GrainBytes; + return max_regions() * HeapRegion::GrainBytes; } void G1CollectedHeap::deduplicate_string(oop str) { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 2f325819186..546a25e7c5d 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -101,7 +101,7 @@ class G1EvacSummary; typedef OverflowTaskQueue<ScannerTask, mtGC> G1ScannerTasksQueue; typedef GenericTaskQueueSet<G1ScannerTasksQueue, mtGC> G1ScannerTasksQueueSet; -typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) +typedef int RegionIdx_t; // needs to hold [ 0..max_reserved_regions() ) typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) // The G1 STW is alive closure. @@ -1061,11 +1061,12 @@ class G1CollectedHeap : public CollectedHeap { // The current number of regions in the heap. uint num_regions() const { return _hrm->length(); } - // The max number of regions in the heap. - uint max_regions() const { return _hrm->max_length(); } + // The max number of regions reserved for the heap. Except for static array + // sizing purposes you probably want to use max_regions(). + uint max_reserved_regions() const { return _hrm->reserved_length(); } - // Max number of regions that can be comitted. - uint max_expandable_regions() const { return _hrm->max_expandable_length(); } + // Max number of regions that can be committed. + uint max_regions() const { return _hrm->max_length(); } // The number of regions that are completely free. uint num_free_regions() const { return _hrm->num_free_regions(); } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 30b2cdeaf7a..db39d0a3d31 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -62,6 +62,7 @@ #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/orderAccess.hpp" @@ -405,8 +406,8 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, _num_concurrent_workers(0), _max_concurrent_workers(0), - _region_mark_stats(NEW_C_HEAP_ARRAY(G1RegionMarkStats, _g1h->max_regions(), mtGC)), - _top_at_rebuild_starts(NEW_C_HEAP_ARRAY(HeapWord*, _g1h->max_regions(), mtGC)) + _region_mark_stats(NEW_C_HEAP_ARRAY(G1RegionMarkStats, _g1h->max_reserved_regions(), mtGC)), + _top_at_rebuild_starts(NEW_C_HEAP_ARRAY(HeapWord*, _g1h->max_reserved_regions(), mtGC)) { assert(CGC_lock != NULL, "CGC_lock must be initialized"); @@ -462,8 +463,8 @@ void G1ConcurrentMark::reset() { _tasks[i]->reset(_next_mark_bitmap); } - uint max_regions = _g1h->max_regions(); - for (uint i = 0; i < max_regions; i++) { + uint max_reserved_regions = _g1h->max_reserved_regions(); + for (uint i = 0; i < max_reserved_regions; i++) { _top_at_rebuild_starts[i] = NULL; _region_mark_stats[i].clear(); } @@ -518,8 +519,8 @@ void G1ConcurrentMark::reset_marking_for_restart() { if (has_overflown()) { _global_mark_stack.expand(); - uint max_regions = _g1h->max_regions(); - for (uint i = 0; i < max_regions; i++) { + uint max_reserved_regions = _g1h->max_reserved_regions(); + for (uint i = 0; i < max_reserved_regions; i++) { _region_mark_stats[i].clear_during_overflow(); } } @@ -1738,8 +1739,7 @@ class G1RemarkThreadsClosure : public ThreadClosure { // * Weakly reachable otherwise // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be // live by the SATB invariant but other oops recorded in nmethods may behave differently. - JavaThread* jt = (JavaThread*)thread; - jt->nmethods_do(&_code_cl); + thread->as_Java_thread()->nmethods_do(&_code_cl); } } } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp index 3189c27db7b..bd797e6eb9c 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp @@ -182,13 +182,13 @@ inline size_t G1CMTask::scan_objArray(objArrayOop obj, MemRegion mr) { } inline HeapWord* G1ConcurrentMark::top_at_rebuild_start(uint region) const { - assert(region < _g1h->max_regions(), "Tried to access TARS for region %u out of bounds", region); + assert(region < _g1h->max_reserved_regions(), "Tried to access TARS for region %u out of bounds", region); return _top_at_rebuild_starts[region]; } inline void G1ConcurrentMark::update_top_at_rebuild_start(HeapRegion* r) { uint const region = r->hrm_index(); - assert(region < _g1h->max_regions(), "Tried to access TARS for region %u out of bounds", region); + assert(region < _g1h->max_reserved_regions(), "Tried to access TARS for region %u out of bounds", region); assert(_top_at_rebuild_starts[region] == NULL, "TARS for region %u has already been set to " PTR_FORMAT " should be NULL", region, p2i(_top_at_rebuild_starts[region])); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index b8bd67eb07a..bb9731f8b41 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -30,6 +30,7 @@ #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/iterator.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/share/gc/g1/g1FromCardCache.cpp b/src/hotspot/share/gc/g1/g1FromCardCache.cpp index 1ef65898ec7..a0dcadde611 100644 --- a/src/hotspot/share/gc/g1/g1FromCardCache.cpp +++ b/src/hotspot/share/gc/g1/g1FromCardCache.cpp @@ -29,26 +29,26 @@ #include "utilities/debug.hpp" uintptr_t** G1FromCardCache::_cache = NULL; -uint G1FromCardCache::_max_regions = 0; +uint G1FromCardCache::_max_reserved_regions = 0; size_t G1FromCardCache::_static_mem_size = 0; #ifdef ASSERT uint G1FromCardCache::_max_workers = 0; #endif -void G1FromCardCache::initialize(uint num_par_rem_sets, uint max_num_regions) { - guarantee(max_num_regions > 0, "Heap size must be valid"); +void G1FromCardCache::initialize(uint num_par_rem_sets, uint max_reserved_regions) { + guarantee(max_reserved_regions > 0, "Heap size must be valid"); guarantee(_cache == NULL, "Should not call this multiple times"); - _max_regions = max_num_regions; + _max_reserved_regions = max_reserved_regions; #ifdef ASSERT _max_workers = num_par_rem_sets; #endif - _cache = Padded2DArray<uintptr_t, mtGC>::create_unfreeable(_max_regions, + _cache = Padded2DArray<uintptr_t, mtGC>::create_unfreeable(_max_reserved_regions, num_par_rem_sets, &_static_mem_size); if (AlwaysPreTouch) { - invalidate(0, _max_regions); + invalidate(0, _max_reserved_regions); } } @@ -57,7 +57,7 @@ void G1FromCardCache::invalidate(uint start_idx, size_t new_num_regions) { "Trying to invalidate beyond maximum region, from %u size " SIZE_FORMAT, start_idx, new_num_regions); uint end_idx = (start_idx + (uint)new_num_regions); - assert(end_idx <= _max_regions, "Must be within max."); + assert(end_idx <= _max_reserved_regions, "Must be within max."); for (uint i = 0; i < G1RemSet::num_par_rem_sets(); i++) { for (uint j = start_idx; j < end_idx; j++) { @@ -69,7 +69,7 @@ void G1FromCardCache::invalidate(uint start_idx, size_t new_num_regions) { #ifndef PRODUCT void G1FromCardCache::print(outputStream* out) { for (uint i = 0; i < G1RemSet::num_par_rem_sets(); i++) { - for (uint j = 0; j < _max_regions; j++) { + for (uint j = 0; j < _max_reserved_regions; j++) { out->print_cr("_from_card_cache[%u][%u] = " SIZE_FORMAT ".", i, j, at(i, j)); } diff --git a/src/hotspot/share/gc/g1/g1FromCardCache.hpp b/src/hotspot/share/gc/g1/g1FromCardCache.hpp index 22f837dd2ef..c234b3021a0 100644 --- a/src/hotspot/share/gc/g1/g1FromCardCache.hpp +++ b/src/hotspot/share/gc/g1/g1FromCardCache.hpp @@ -38,14 +38,14 @@ class G1FromCardCache : public AllStatic { // freeing. I.e. a single clear of a single memory area instead of multiple separate // accesses with a large stride per region. static uintptr_t** _cache; - static uint _max_regions; + static uint _max_reserved_regions; static size_t _static_mem_size; #ifdef ASSERT static uint _max_workers; static void check_bounds(uint worker_id, uint region_idx) { assert(worker_id < _max_workers, "Worker_id %u is larger than maximum %u", worker_id, _max_workers); - assert(region_idx < _max_regions, "Region_idx %u is larger than maximum %u", region_idx, _max_regions); + assert(region_idx < _max_reserved_regions, "Region_idx %u is larger than maximum %u", region_idx, _max_reserved_regions); } #endif @@ -79,7 +79,7 @@ class G1FromCardCache : public AllStatic { _cache[region_idx][worker_id] = val; } - static void initialize(uint num_par_rem_sets, uint max_num_regions); + static void initialize(uint num_par_rem_sets, uint max_reserved_regions); static void invalidate(uint start_idx, size_t num_regions); diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index c7bda3940f2..1357393f2b9 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -46,6 +46,7 @@ #include "gc/shared/gcPolicyCounters.hpp" #include "logging/log.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/debug.hpp" @@ -61,8 +62,8 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) : _ihop_control(create_ihop_control(&_old_gen_alloc_tracker, &_predictor)), _policy_counters(new GCPolicyCounters("GarbageFirst", 1, 2)), _full_collection_start_sec(0.0), + _young_list_desired_length(0), _young_list_target_length(0), - _young_list_fixed_length(0), _young_list_max_length(0), _eden_surv_rate_group(new G1SurvRateGroup()), _survivor_surv_rate_group(new G1SurvRateGroup()), @@ -107,14 +108,11 @@ void G1Policy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) { assert(Heap_lock->owned_by_self(), "Locking discipline."); - if (!use_adaptive_young_list_length()) { - _young_list_fixed_length = _young_gen_sizer->min_desired_young_length(); - } - _young_gen_sizer->adjust_max_new_size(_g1h->max_expandable_regions()); + _young_gen_sizer->adjust_max_new_size(_g1h->max_regions()); _free_regions_at_end_of_collection = _g1h->num_free_regions(); - update_young_list_max_and_target_length(); + update_young_length_bounds(); // We may immediately start allocating regions and placing them on the // collection set list. Initialize the per-collection set info _collection_set->start_incremental_building(); @@ -189,158 +187,255 @@ void G1Policy::record_new_heap_size(uint new_number_of_regions) { _ihop_control->update_target_occupancy(new_number_of_regions * HeapRegion::GrainBytes); } -uint G1Policy::calculate_young_list_desired_min_length(uint base_min_length) const { +uint G1Policy::calculate_desired_eden_length_by_mmu() const { + // One could argue that any useful eden length to keep any MMU would be 1, but + // in theory this is possible. Other constraints enforce a minimum eden of 1 + // anyway. uint desired_min_length = 0; if (use_adaptive_young_list_length()) { - if (_analytics->num_alloc_rate_ms() > 3) { - double now_sec = os::elapsedTime(); - double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; - double alloc_rate_ms = _analytics->predict_alloc_rate_ms(); - desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); - } else { - // otherwise we don't have enough info to make the prediction - } + double now_sec = os::elapsedTime(); + double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; + double alloc_rate_ms = _analytics->predict_alloc_rate_ms(); + desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); } - desired_min_length += base_min_length; - // make sure we don't go below any user-defined minimum bound - return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length); -} - -uint G1Policy::calculate_young_list_desired_max_length() const { - // Here, we might want to also take into account any additional - // constraints (i.e., user-defined minimum bound). Currently, we - // effectively don't set this bound. - return _young_gen_sizer->max_desired_young_length(); -} - -uint G1Policy::update_young_list_max_and_target_length() { - return update_young_list_max_and_target_length(_analytics->predict_rs_length()); -} - -uint G1Policy::update_young_list_max_and_target_length(size_t rs_length) { - uint unbounded_target_length = update_young_list_target_length(rs_length); - update_max_gc_locker_expansion(); - return unbounded_target_length; -} + return desired_min_length; +} + +void G1Policy::update_young_length_bounds() { + update_young_length_bounds(_analytics->predict_rs_length()); +} + +void G1Policy::update_young_length_bounds(size_t rs_length) { + _young_list_desired_length = calculate_young_desired_length(rs_length); + _young_list_target_length = calculate_young_target_length(_young_list_desired_length); + _young_list_max_length = calculate_young_max_length(_young_list_target_length); + + log_debug(gc,ergo,heap)("Young list lengths: desired: %u, target: %u, max: %u", + _young_list_desired_length, + _young_list_target_length, + _young_list_max_length); +} + +// Calculates desired young gen length. It is calculated from: +// +// - sizer min/max bounds on young gen +// - pause time goal for whole young gen evacuation +// - MMU goal influencing eden to make GCs spaced apart. +// - a minimum one eden region length. +// +// We may enter with already allocated eden and survivor regions, that may be +// higher than the maximum, or the above goals may result in a desired value +// smaller than are already allocated. +// The main reason is revising young length, with or without the GCLocker being +// active. +// +uint G1Policy::calculate_young_desired_length(size_t rs_length) const { + uint min_young_length_by_sizer = _young_gen_sizer->min_desired_young_length(); + uint max_young_length_by_sizer = _young_gen_sizer->max_desired_young_length(); + + assert(min_young_length_by_sizer >= 1, "invariant"); + assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant"); + + // Absolute minimum eden length. + // Enforcing a minimum eden length helps at startup when the predictors are not + // yet trained on the application to avoid unnecessary (but very short) full gcs + // on very small (initial) heaps. + uint const MinDesiredEdenLength = 1; -uint G1Policy::update_young_list_target_length(size_t rs_length) { - YoungTargetLengths young_lengths = young_list_target_lengths(rs_length); - _young_list_target_length = young_lengths.first; + // Calculate the absolute and desired min bounds first. - return young_lengths.second; -} + // This is how many survivor regions we already have. + const uint survivor_length = _g1h->survivor_regions_count(); + // Size of the already allocated young gen. + const uint allocated_young_length = _g1h->young_regions_count(); + // This is the absolute minimum young length that we can return. Ensure that we + // don't go below any user-defined minimum bound; but we might have already + // allocated more than that for various reasons. In this case, use that. + uint absolute_min_young_length = MAX2(allocated_young_length, min_young_length_by_sizer); + // Calculate the absolute max bounds. After evac failure or when revising the + // young length we might have exceeded absolute min length or absolute_max_length, + // so adjust the result accordingly. + uint absolute_max_young_length = MAX2(max_young_length_by_sizer, absolute_min_young_length); + + uint desired_eden_length_by_mmu = 0; + uint desired_eden_length_by_pause = 0; + + uint desired_young_length = 0; + if (use_adaptive_young_list_length()) { + desired_eden_length_by_mmu = calculate_desired_eden_length_by_mmu(); -G1Policy::YoungTargetLengths G1Policy::young_list_target_lengths(size_t rs_length) const { - YoungTargetLengths result; + const size_t pending_cards = _analytics->predict_pending_cards(); + double survivor_base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length); - // Calculate the absolute and desired min bounds first. + desired_eden_length_by_pause = + calculate_desired_eden_length_by_pause(survivor_base_time_ms, + absolute_min_young_length - survivor_length, + absolute_max_young_length - survivor_length); - // This is how many young regions we already have (currently: the survivors). - const uint base_min_length = _g1h->survivor_regions_count(); - uint desired_min_length = calculate_young_list_desired_min_length(base_min_length); - // This is the absolute minimum young length. Ensure that we - // will at least have one eden region available for allocation. - uint absolute_min_length = base_min_length + MAX2(_g1h->eden_regions_count(), (uint)1); - // If we shrank the young list target it should not shrink below the current size. - desired_min_length = MAX2(desired_min_length, absolute_min_length); - // Calculate the absolute and desired max bounds. + // Incorporate MMU concerns; assume that it overrides the pause time + // goal, as the default value has been chosen to effectively disable it. + // Also request at least one eden region, see above for reasons. + uint desired_eden_length = MAX3(desired_eden_length_by_pause, + desired_eden_length_by_mmu, + MinDesiredEdenLength); - uint desired_max_length = calculate_young_list_desired_max_length(); - - uint young_list_target_length = 0; - if (use_adaptive_young_list_length()) { - if (collector_state()->in_young_only_phase()) { - young_list_target_length = - calculate_young_list_target_length(rs_length, - base_min_length, - desired_min_length, - desired_max_length); - } else { - // Don't calculate anything and let the code below bound it to - // the desired_min_length, i.e., do the next GC as soon as - // possible to maximize how many old regions we can add to it. - } + desired_young_length = desired_eden_length + survivor_length; } else { // The user asked for a fixed young gen so we'll fix the young gen // whether the next GC is young or mixed. - young_list_target_length = _young_list_fixed_length; - } - - result.second = young_list_target_length; - - // We will try our best not to "eat" into the reserve. - uint absolute_max_length = 0; - if (_free_regions_at_end_of_collection > _reserve_regions) { - absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions; + desired_young_length = min_young_length_by_sizer; } - if (desired_max_length > absolute_max_length) { - desired_max_length = absolute_max_length; + // Clamp to absolute min/max after we determined desired lengths. + desired_young_length = clamp(desired_young_length, absolute_min_young_length, absolute_max_young_length); + + log_trace(gc, ergo, heap)("Young desired length %u " + "survivor length %u " + "allocated young length %u " + "absolute min young length %u " + "absolute max young length %u " + "desired eden length by mmu %u " + "desired eden length by pause %u " + "desired eden length by default %u", + desired_young_length, survivor_length, + allocated_young_length, absolute_min_young_length, + absolute_max_young_length, desired_eden_length_by_mmu, + desired_eden_length_by_pause, + MinDesiredEdenLength); + + assert(desired_young_length >= allocated_young_length, "must be"); + return desired_young_length; +} + +// Limit the desired (wished) young length by current free regions. If the request +// can be satisfied without using up reserve regions, do so, otherwise eat into +// the reserve, giving away at most what the heap sizer allows. +uint G1Policy::calculate_young_target_length(uint desired_young_length) const { + uint allocated_young_length = _g1h->young_regions_count(); + + uint receiving_additional_eden; + if (allocated_young_length >= desired_young_length) { + // Already used up all we actually want (may happen as G1 revises the + // young list length concurrently, or caused by gclocker). Do not allow more, + // potentially resulting in GC. + receiving_additional_eden = 0; + log_trace(gc, ergo, heap)("Young target length: Already used up desired young %u allocated %u", + desired_young_length, + allocated_young_length); + } else { + // Now look at how many free regions are there currently, and the heap reserve. + // We will try our best not to "eat" into the reserve as long as we can. If we + // do, we at most eat the sizer's minimum regions into the reserve or half the + // reserve rounded up (if possible; this is an arbitrary value). + + uint max_to_eat_into_reserve = MIN2(_young_gen_sizer->min_desired_young_length(), + (_reserve_regions + 1) / 2); + + log_trace(gc, ergo, heap)("Young target length: Common " + "free regions at end of collection %u " + "desired young length %u " + "reserve region %u " + "max to eat into reserve %u", + _free_regions_at_end_of_collection, + desired_young_length, + _reserve_regions, + max_to_eat_into_reserve); + + if (_free_regions_at_end_of_collection <= _reserve_regions) { + // Fully eat (or already eating) into the reserve, hand back at most absolute_min_length regions. + uint receiving_young = MIN3(_free_regions_at_end_of_collection, + desired_young_length, + max_to_eat_into_reserve); + // We could already have allocated more regions than what we could get + // above. + receiving_additional_eden = allocated_young_length < receiving_young ? + receiving_young - allocated_young_length : 0; + + log_trace(gc, ergo, heap)("Young target length: Fully eat into reserve " + "receiving young %u receiving additional eden %u", + receiving_young, + receiving_additional_eden); + } else if (_free_regions_at_end_of_collection < (desired_young_length + _reserve_regions)) { + // Partially eat into the reserve, at most max_to_eat_into_reserve regions. + uint free_outside_reserve = _free_regions_at_end_of_collection - _reserve_regions; + assert(free_outside_reserve < desired_young_length, + "must be %u %u", + free_outside_reserve, desired_young_length); + + uint receiving_within_reserve = MIN2(desired_young_length - free_outside_reserve, + max_to_eat_into_reserve); + uint receiving_young = free_outside_reserve + receiving_within_reserve; + // Again, we could have already allocated more than we could get. + receiving_additional_eden = allocated_young_length < receiving_young ? + receiving_young - allocated_young_length : 0; + + log_trace(gc, ergo, heap)("Young target length: Partially eat into reserve " + "free outside reserve %u " + "receiving within reserve %u " + "receiving young %u " + "receiving additional eden %u", + free_outside_reserve, receiving_within_reserve, + receiving_young, receiving_additional_eden); + } else { + // No need to use the reserve. + receiving_additional_eden = desired_young_length - allocated_young_length; + log_trace(gc, ergo, heap)("Young target length: No need to use reserve " + "receiving additional eden %u", + receiving_additional_eden); + } } - // Make sure we don't go over the desired max length, nor under the - // desired min length. In case they clash, desired_min_length wins - // which is why that test is second. - if (young_list_target_length > desired_max_length) { - young_list_target_length = desired_max_length; - } - if (young_list_target_length < desired_min_length) { - young_list_target_length = desired_min_length; - } + uint target_young_length = allocated_young_length + receiving_additional_eden; - assert(young_list_target_length > base_min_length, - "we should be able to allocate at least one eden region"); - assert(young_list_target_length >= absolute_min_length, "post-condition"); + assert(target_young_length >= allocated_young_length, "must be"); - result.first = young_list_target_length; - return result; + log_trace(gc, ergo, heap)("Young target length: " + "young target length %u " + "allocated young length %u " + "received additional eden %u", + target_young_length, allocated_young_length, + receiving_additional_eden); + return target_young_length; } -uint G1Policy::calculate_young_list_target_length(size_t rs_length, - uint base_min_length, - uint desired_min_length, - uint desired_max_length) const { - assert(use_adaptive_young_list_length(), "pre-condition"); - assert(collector_state()->in_young_only_phase(), "only call this for young GCs"); - - // In case some edge-condition makes the desired max length too small... - if (desired_max_length <= desired_min_length) { - return desired_min_length; +uint G1Policy::calculate_desired_eden_length_by_pause(double base_time_ms, + uint min_eden_length, + uint max_eden_length) const { + if (!next_gc_should_be_mixed(NULL, NULL)) { + return calculate_desired_eden_length_before_young_only(base_time_ms, + min_eden_length, + max_eden_length); + } else { + return calculate_desired_eden_length_before_mixed(base_time_ms, + min_eden_length, + max_eden_length); } +} + + +uint G1Policy::calculate_desired_eden_length_before_young_only(double base_time_ms, + uint min_eden_length, + uint max_eden_length) const { + assert(use_adaptive_young_list_length(), "pre-condition"); - // We'll adjust min_young_length and max_young_length not to include - // the already allocated young regions (i.e., so they reflect the - // min and max eden regions we'll allocate). The base_min_length - // will be reflected in the predictions by the - // survivor_regions_evac_time prediction. - assert(desired_min_length > base_min_length, "invariant"); - uint min_young_length = desired_min_length - base_min_length; - assert(desired_max_length > base_min_length, "invariant"); - uint max_young_length = desired_max_length - base_min_length; - - const double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; - const size_t pending_cards = _analytics->predict_pending_cards(); - const double base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length); - const uint available_free_regions = _free_regions_at_end_of_collection; - const uint base_free_regions = - available_free_regions > _reserve_regions ? available_free_regions - _reserve_regions : 0; + assert(min_eden_length <= max_eden_length, "must be %u %u", min_eden_length, max_eden_length); // Here, we will make sure that the shortest young length that // makes sense fits within the target pause time. G1YoungLengthPredictor p(base_time_ms, - base_free_regions, - target_pause_time_ms, + _free_regions_at_end_of_collection, + _mmu_tracker->max_gc_time() * 1000.0, this); - if (p.will_fit(min_young_length)) { + if (p.will_fit(min_eden_length)) { // The shortest young length will fit into the target pause time; // we'll now check whether the absolute maximum number of young // regions will fit in the target pause time. If not, we'll do // a binary search between min_young_length and max_young_length. - if (p.will_fit(max_young_length)) { + if (p.will_fit(max_eden_length)) { // The maximum young length will fit into the target pause time. // We are done so set min young length to the maximum length (as // the result is assumed to be returned in min_young_length). - min_young_length = max_young_length; + min_eden_length = max_eden_length; } else { // The maximum possible number of young regions will not fit within // the target pause time so we'll search for the optimal @@ -357,37 +452,56 @@ uint G1Policy::calculate_young_list_target_length(size_t rs_length, // does, it becomes the new min. If it doesn't, it becomes // the new max. This way we maintain the loop invariants. - assert(min_young_length < max_young_length, "invariant"); - uint diff = (max_young_length - min_young_length) / 2; + assert(min_eden_length < max_eden_length, "invariant"); + uint diff = (max_eden_length - min_eden_length) / 2; while (diff > 0) { - uint young_length = min_young_length + diff; - if (p.will_fit(young_length)) { - min_young_length = young_length; + uint eden_length = min_eden_length + diff; + if (p.will_fit(eden_length)) { + min_eden_length = eden_length; } else { - max_young_length = young_length; + max_eden_length = eden_length; } - assert(min_young_length < max_young_length, "invariant"); - diff = (max_young_length - min_young_length) / 2; + assert(min_eden_length < max_eden_length, "invariant"); + diff = (max_eden_length - min_eden_length) / 2; } // The results is min_young_length which, according to the // loop invariants, should fit within the target pause time. // These are the post-conditions of the binary search above: - assert(min_young_length < max_young_length, - "otherwise we should have discovered that max_young_length " + assert(min_eden_length < max_eden_length, + "otherwise we should have discovered that max_eden_length " "fits into the pause target and not done the binary search"); - assert(p.will_fit(min_young_length), - "min_young_length, the result of the binary search, should " + assert(p.will_fit(min_eden_length), + "min_eden_length, the result of the binary search, should " "fit into the pause target"); - assert(!p.will_fit(min_young_length + 1), - "min_young_length, the result of the binary search, should be " + assert(!p.will_fit(min_eden_length + 1), + "min_eden_length, the result of the binary search, should be " "optimal, so no larger length should fit into the pause target"); } } else { // Even the minimum length doesn't fit into the pause time // target, return it as the result nevertheless. } - return base_min_length + min_young_length; + return min_eden_length; +} + +uint G1Policy::calculate_desired_eden_length_before_mixed(double survivor_base_time_ms, + uint min_eden_length, + uint max_eden_length) const { + G1CollectionSetCandidates* candidates = _collection_set->candidates(); + + uint min_old_regions_end = MIN2(candidates->cur_idx() + calc_min_old_cset_length(), candidates->num_regions()); + double predicted_region_evac_time_ms = survivor_base_time_ms; + for (uint i = candidates->cur_idx(); i < min_old_regions_end; i++) { + HeapRegion* r = candidates->at(i); + predicted_region_evac_time_ms += predict_region_total_time_ms(r, false); + } + uint desired_eden_length_by_min_cset_length = + calculate_desired_eden_length_before_young_only(predicted_region_evac_time_ms, + min_eden_length, + max_eden_length); + + return desired_eden_length_by_min_cset_length; } double G1Policy::predict_survivor_regions_evac_time() const { @@ -417,8 +531,7 @@ void G1Policy::revise_young_list_target_length_if_necessary(size_t rs_length) { // add 10% to avoid having to recalculate often size_t rs_length_prediction = rs_length * 1100 / 1000; update_rs_length_prediction(rs_length_prediction); - - update_young_list_max_and_target_length(rs_length_prediction); + update_young_length_bounds(rs_length_prediction); } } @@ -466,7 +579,7 @@ void G1Policy::record_full_collection_end() { _free_regions_at_end_of_collection = _g1h->num_free_regions(); _survivor_surv_rate_group->reset(); - update_young_list_max_and_target_length(); + update_young_length_bounds(); update_rs_length_prediction(); _old_gen_alloc_tracker.reset_after_gc(_g1h->humongous_regions_count() * HeapRegion::GrainBytes); @@ -798,15 +911,10 @@ void G1Policy::record_collection_pause_end(double pause_time_ms) { // Do not update dynamic IHOP due to G1 periodic collection as it is highly likely // that in this case we are not running in a "normal" operating mode. if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) { - // IHOP control wants to know the expected young gen length if it were not - // restrained by the heap reserve. Using the actual length would make the - // prediction too small and the limit the young gen every time we get to the - // predicted target occupancy. - size_t last_unrestrained_young_length = update_young_list_max_and_target_length(); + update_young_length_bounds(); _old_gen_alloc_tracker.reset_after_gc(_g1h->humongous_regions_count() * HeapRegion::GrainBytes); update_ihop_prediction(app_time_ms / 1000.0, - last_unrestrained_young_length * HeapRegion::GrainBytes, is_young_only_pause(this_pause)); _ihop_control->send_trace_event(_g1h->gc_tracer_stw()); @@ -857,7 +965,6 @@ G1IHOPControl* G1Policy::create_ihop_control(const G1OldGenAllocationTracker* ol } void G1Policy::update_ihop_prediction(double mutator_time_s, - size_t young_gen_size, bool this_gc_was_young_only) { // Always try to update IHOP prediction. Even evacuation failures give information // about e.g. whether to start IHOP earlier next time. @@ -885,6 +992,11 @@ void G1Policy::update_ihop_prediction(double mutator_time_s, // marking, which makes any prediction useless. This increases the accuracy of the // prediction. if (this_gc_was_young_only && mutator_time_s > min_valid_time) { + // IHOP control wants to know the expected young gen length if it were not + // restrained by the heap reserve. Using the actual length would make the + // prediction too small and the limit the young gen every time we get to the + // predicted target occupancy. + size_t young_gen_size = young_list_desired_length() * HeapRegion::GrainBytes; _ihop_control->update_allocation_info(mutator_time_s, young_gen_size); report = true; } @@ -991,7 +1103,7 @@ void G1Policy::print_age_table() { _survivors_age_table.print_age_table(_tenuring_threshold); } -void G1Policy::update_max_gc_locker_expansion() { +uint G1Policy::calculate_young_max_length(uint target_young_length) const { uint expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { double perc = (double) GCLockerEdenExpansionPercent / 100.0; @@ -999,11 +1111,10 @@ void G1Policy::update_max_gc_locker_expansion() { // We use ceiling so that if expansion_region_num_d is > 0.0 (but // less than 1.0) we'll get 1. expansion_region_num = (uint) ceil(expansion_region_num_d); - } else { - assert(expansion_region_num == 0, "sanity"); } - _young_list_max_length = _young_list_target_length + expansion_region_num; - assert(_young_list_target_length <= _young_list_max_length, "post-condition"); + uint max_length = target_young_length + expansion_region_num; + assert(target_young_length <= max_length, "overflow"); + return max_length; } // Calculates survivor space parameters. @@ -1238,8 +1349,10 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) const { G1CollectionSetCandidates* candidates = _collection_set->candidates(); - if (candidates->is_empty()) { - log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); + if (candidates == NULL || candidates->is_empty()) { + if (false_action_str != NULL) { + log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); + } return false; } @@ -1248,12 +1361,24 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes); double threshold = (double) G1HeapWastePercent; if (reclaimable_percent <= threshold) { - log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, - false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + if (false_action_str != NULL) { + log_debug(gc, ergo)("%s (reclaimable percentage below threshold). " + "candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) " + "threshold: " UINTX_FORMAT, + false_action_str, + candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, + G1HeapWastePercent); + } return false; } - log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, - true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + if (true_action_str != NULL) { + log_debug(gc, ergo)("%s (candidate old regions available). " + "candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) " + "threshold: " UINTX_FORMAT, + true_action_str, + candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, + G1HeapWastePercent); + } return true; } diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index dff561fbdc8..677b012ffd8 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -60,7 +60,6 @@ class G1Policy: public CHeapObj<mtGC> { const G1Predictions* predictor); // Update the IHOP control with necessary statistics. void update_ihop_prediction(double mutator_time_s, - size_t young_gen_size, bool this_gc_was_young_only); void report_ihop_statistics(); @@ -78,8 +77,8 @@ class G1Policy: public CHeapObj<mtGC> { double _full_collection_start_sec; + uint _young_list_desired_length; uint _young_list_target_length; - uint _young_list_fixed_length; // The max number of regions we can extend the eden by while the GC // locker is active. This should be >= _young_list_target_length; @@ -168,6 +167,10 @@ class G1Policy: public CHeapObj<mtGC> { private: G1CollectionSet* _collection_set; + + bool next_gc_should_be_mixed(const char* true_action_str, + const char* false_action_str) const; + double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const; double other_time_ms(double pause_time_ms) const; @@ -189,44 +192,44 @@ class G1Policy: public CHeapObj<mtGC> { double _mark_remark_start_sec; double _mark_cleanup_start_sec; - // Updates the internal young list maximum and target lengths. Returns the - // unbounded young list target length. If no rs_length parameter is passed, - // predict the RS length using the prediction model, otherwise use the - // given rs_length as the prediction. - uint update_young_list_max_and_target_length(); - uint update_young_list_max_and_target_length(size_t rs_length); - - // Update the young list target length either by setting it to the - // desired fixed value or by calculating it using G1's pause - // prediction model. - // Returns the unbounded young list target length. - uint update_young_list_target_length(size_t rs_length); - - // Calculate and return the minimum desired young list target - // length. This is the minimum desired young list length according - // to the user's inputs. - uint calculate_young_list_desired_min_length(uint base_min_length) const; - - // Calculate and return the maximum desired young list target - // length. This is the maximum desired young list length according - // to the user's inputs. - uint calculate_young_list_desired_max_length() const; - - // Calculate and return the maximum young list target length that - // can fit into the pause time goal. The parameters are: rs_length - // represent the prediction of how large the young RSet lengths will - // be, base_min_length is the already existing number of regions in - // the young list, min_length and max_length are the desired min and - // max young list length according to the user's inputs. - uint calculate_young_list_target_length(size_t rs_length, - uint base_min_length, - uint desired_min_length, - uint desired_max_length) const; - - // Result of the bounded_young_list_target_length() method, containing both the - // bounded as well as the unbounded young list target lengths in this order. - typedef Pair<uint, uint, StackObj> YoungTargetLengths; - YoungTargetLengths young_list_target_lengths(size_t rs_length) const; + // Updates the internal young gen maximum and target and desired lengths. + // If no rs_length parameter is passed, predict the RS length using the + // prediction model, otherwise use the given rs_length as the prediction. + void update_young_length_bounds(); + void update_young_length_bounds(size_t rs_length); + + // Calculate and return the minimum desired eden length based on the MMU target. + uint calculate_desired_eden_length_by_mmu() const; + + // Calculate the desired eden length meeting the pause time goal. + // The parameters are: rs_length represents the prediction of how large the + // young RSet lengths will be, min_eden_length and max_eden_length are the bounds + // (inclusive) within eden can grow. + uint calculate_desired_eden_length_by_pause(double base_time_ms, + uint min_eden_length, + uint max_eden_length) const; + + // Calculate the desired eden length that can fit into the pause time + // goal before young only gcs. + uint calculate_desired_eden_length_before_young_only(double base_time_ms, + uint min_eden_length, + uint max_eden_length) const; + + // Calculates the desired eden length before mixed gc so that after adding the + // minimum amount of old gen regions from the collection set, the eden fits into + // the pause time goal. + uint calculate_desired_eden_length_before_mixed(double survivor_base_time_ms, + uint min_eden_length, + uint max_eden_length) const; + + // Calculate desired young length based on current situation without taking actually + // available free regions into account. + uint calculate_young_desired_length(size_t rs_length) const; + // Limit the given desired young length to available free regions. + uint calculate_young_target_length(uint desired_young_length) const; + // The GCLocker might cause us to need more regions than the target. Calculate + // the maximum number of regions to use in that case. + uint calculate_young_max_length(uint target_young_length) const; void update_rs_length_prediction(); void update_rs_length_prediction(size_t prediction); @@ -337,9 +340,6 @@ class G1Policy: public CHeapObj<mtGC> { void print_phases(); - bool next_gc_should_be_mixed(const char* true_action_str, - const char* false_action_str) const; - // Calculate and return the number of initial and optional old gen regions from // the given collection set candidates and the remaining time. void calculate_old_collection_set_regions(G1CollectionSetCandidates* candidates, @@ -376,6 +376,7 @@ class G1Policy: public CHeapObj<mtGC> { // the concurrent start work and start a marking cycle. void decide_on_conc_mark_initiation(); + uint young_list_desired_length() const { return _young_list_desired_length; } size_t young_list_target_length() const { return _young_list_target_length; } bool should_allocate_mutator_region() const; @@ -436,8 +437,6 @@ class G1Policy: public CHeapObj<mtGC> { void print_age_table(); - void update_max_gc_locker_expansion(); - void update_survivors_policy(); virtual bool force_upgrade_to_full() { diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index 354cc5ed8f0..7ff5bce8694 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -86,7 +86,7 @@ class G1RemSetScanState : public CHeapObj<mtGC> { class G1DirtyRegions; - size_t _max_regions; + size_t _max_reserved_regions; // Has this region that is part of the regions in the collection set been processed yet. typedef bool G1RemsetIterState; @@ -141,16 +141,16 @@ class G1RemSetScanState : public CHeapObj<mtGC> { class G1DirtyRegions : public CHeapObj<mtGC> { uint* _buffer; uint _cur_idx; - size_t _max_regions; + size_t _max_reserved_regions; bool* _contains; public: - G1DirtyRegions(size_t max_regions) : - _buffer(NEW_C_HEAP_ARRAY(uint, max_regions, mtGC)), + G1DirtyRegions(size_t max_reserved_regions) : + _buffer(NEW_C_HEAP_ARRAY(uint, max_reserved_regions, mtGC)), _cur_idx(0), - _max_regions(max_regions), - _contains(NEW_C_HEAP_ARRAY(bool, max_regions, mtGC)) { + _max_reserved_regions(max_reserved_regions), + _contains(NEW_C_HEAP_ARRAY(bool, max_reserved_regions, mtGC)) { reset(); } @@ -164,7 +164,7 @@ class G1RemSetScanState : public CHeapObj<mtGC> { void reset() { _cur_idx = 0; - ::memset(_contains, false, _max_regions * sizeof(bool)); + ::memset(_contains, false, _max_reserved_regions * sizeof(bool)); } uint size() const { return _cur_idx; } @@ -273,7 +273,7 @@ class G1RemSetScanState : public CHeapObj<mtGC> { public: G1RemSetScanState() : - _max_regions(0), + _max_reserved_regions(0), _collection_set_iter_state(NULL), _card_table_scan_state(NULL), _scan_chunks_per_region(get_chunks_per_region(HeapRegion::LogOfHRGrainBytes)), @@ -293,16 +293,16 @@ class G1RemSetScanState : public CHeapObj<mtGC> { FREE_C_HEAP_ARRAY(HeapWord*, _scan_top); } - void initialize(size_t max_regions) { + void initialize(size_t max_reserved_regions) { assert(_collection_set_iter_state == NULL, "Must not be initialized twice"); - _max_regions = max_regions; - _collection_set_iter_state = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC); - _card_table_scan_state = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC); - _num_total_scan_chunks = max_regions * _scan_chunks_per_region; + _max_reserved_regions = max_reserved_regions; + _collection_set_iter_state = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_reserved_regions, mtGC); + _card_table_scan_state = NEW_C_HEAP_ARRAY(uint, max_reserved_regions, mtGC); + _num_total_scan_chunks = max_reserved_regions * _scan_chunks_per_region; _region_scan_chunks = NEW_C_HEAP_ARRAY(bool, _num_total_scan_chunks, mtGC); _scan_chunks_shift = (uint8_t)log2_intptr(HeapRegion::CardsPerRegion / _scan_chunks_per_region); - _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC); + _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_reserved_regions, mtGC); } void prepare() { @@ -310,20 +310,20 @@ class G1RemSetScanState : public CHeapObj<mtGC> { // regions currently not available or free. Since regions might // become used during the collection these values must be valid // for those regions as well. - for (size_t i = 0; i < _max_regions; i++) { + for (size_t i = 0; i < _max_reserved_regions; i++) { reset_region_claim((uint)i); clear_scan_top((uint)i); } - _all_dirty_regions = new G1DirtyRegions(_max_regions); - _next_dirty_regions = new G1DirtyRegions(_max_regions); + _all_dirty_regions = new G1DirtyRegions(_max_reserved_regions); + _next_dirty_regions = new G1DirtyRegions(_max_reserved_regions); } void prepare_for_merge_heap_roots() { _all_dirty_regions->merge(_next_dirty_regions); _next_dirty_regions->reset(); - for (size_t i = 0; i < _max_regions; i++) { + for (size_t i = 0; i < _max_reserved_regions; i++) { _card_table_scan_state[i] = 0; } @@ -416,7 +416,7 @@ class G1RemSetScanState : public CHeapObj<mtGC> { // Attempt to claim the given region in the collection set for iteration. Returns true // if this call caused the transition from Unclaimed to Claimed. inline bool claim_collection_set_region(uint region) { - assert(region < _max_regions, "Tried to access invalid region %u", region); + assert(region < _max_reserved_regions, "Tried to access invalid region %u", region); if (_collection_set_iter_state[region]) { return false; } @@ -424,12 +424,12 @@ class G1RemSetScanState : public CHeapObj<mtGC> { } bool has_cards_to_scan(uint region) { - assert(region < _max_regions, "Tried to access invalid region %u", region); + assert(region < _max_reserved_regions, "Tried to access invalid region %u", region); return _card_table_scan_state[region] < HeapRegion::CardsPerRegion; } uint claim_cards_to_scan(uint region, uint increment) { - assert(region < _max_regions, "Tried to access invalid region %u", region); + assert(region < _max_reserved_regions, "Tried to access invalid region %u", region); return Atomic::fetch_and_add(&_card_table_scan_state[region], increment); } @@ -485,9 +485,9 @@ uint G1RemSet::num_par_rem_sets() { return G1DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads); } -void G1RemSet::initialize(uint max_regions) { - G1FromCardCache::initialize(num_par_rem_sets(), max_regions); - _scan_state->initialize(max_regions); +void G1RemSet::initialize(uint max_reserved_regions) { + G1FromCardCache::initialize(num_par_rem_sets(), max_reserved_regions); + _scan_state->initialize(max_reserved_regions); } // Helper class to scan and detect ranges of cards that need to be scanned on the diff --git a/src/hotspot/share/gc/g1/g1RemSet.hpp b/src/hotspot/share/gc/g1/g1RemSet.hpp index 186c52e5211..e2762758053 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.hpp +++ b/src/hotspot/share/gc/g1/g1RemSet.hpp @@ -78,7 +78,7 @@ class G1RemSet: public CHeapObj<mtGC> { static uint num_par_rem_sets(); // Initialize data that depends on the heap size being known. - void initialize(uint max_regions); + void initialize(uint max_reserved_regions); G1RemSet(G1CollectedHeap* g1h, G1CardTable* ct, diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index 202af2e70cf..8cc6e0c814e 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -35,13 +35,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ @@ -51,7 +45,7 @@ "attempts to start marking in time based on application " \ "behavior.") \ \ - experimental(size_t, G1AdaptiveIHOPNumInitialSamples, 3, \ + product(size_t, G1AdaptiveIHOPNumInitialSamples, 3, EXPERIMENTAL, \ "How many completed time periods from concurrent start to first " \ "mixed gc are required to use the input values for prediction " \ "of the optimal occupancy to start marking.") \ @@ -61,7 +55,7 @@ "Confidence level for MMU/pause predictions") \ range(0, 100) \ \ - diagnostic(intx, G1SummarizeRSetStatsPeriod, 0, \ + product(intx, G1SummarizeRSetStatsPeriod, 0, DIAGNOSTIC, \ "The period (in number of GCs) at which we will generate " \ "update buffer processing info " \ "(0 means do not periodically generate this info); " \ @@ -79,11 +73,11 @@ "draining concurrent marking work queues.") \ range(1, INT_MAX) \ \ - experimental(bool, G1UseReferencePrecleaning, true, \ + product(bool, G1UseReferencePrecleaning, true, EXPERIMENTAL, \ "Concurrently preclean java.lang.ref.references instances " \ "before the Remark pause.") \ \ - experimental(double, G1LastPLABAverageOccupancy, 50.0, \ + product(double, G1LastPLABAverageOccupancy, 50.0, EXPERIMENTAL, \ "The expected average occupancy of the last PLAB in " \ "percent.") \ range(0.001, 100.0) \ @@ -104,7 +98,7 @@ "specifies that mutator threads should not do such filtering.") \ range(0, 100) \ \ - experimental(intx, G1ExpandByPercentOfAvailable, 20, \ + product(intx, G1ExpandByPercentOfAvailable, 20, EXPERIMENTAL, \ "When expanding, % of uncommitted space to claim.") \ range(0, 100) \ \ @@ -212,19 +206,19 @@ "Raise a fatal VM exit out of memory failure in the event " \ " that heap expansion fails due to running out of swap.") \ \ - experimental(uintx, G1MaxNewSizePercent, 60, \ + product(uintx, G1MaxNewSizePercent, 60, EXPERIMENTAL, \ "Percentage (0-100) of the heap size to use as default " \ " maximum young gen size.") \ range(0, 100) \ constraint(G1MaxNewSizePercentConstraintFunc,AfterErgo) \ \ - experimental(uintx, G1NewSizePercent, 5, \ + product(uintx, G1NewSizePercent, 5, EXPERIMENTAL, \ "Percentage (0-100) of the heap size to use as default " \ "minimum young gen size.") \ range(0, 100) \ constraint(G1NewSizePercentConstraintFunc,AfterErgo) \ \ - experimental(uintx, G1MixedGCLiveThresholdPercent, 85, \ + product(uintx, G1MixedGCLiveThresholdPercent, 85, EXPERIMENTAL, \ "Threshold for regions to be considered for inclusion in the " \ "collection set of mixed GCs. " \ "Regions with live bytes exceeding this will not be collected.") \ @@ -239,18 +233,18 @@ "The target number of mixed GCs after a marking cycle.") \ range(0, max_uintx) \ \ - experimental(bool, G1EagerReclaimHumongousObjects, true, \ + product(bool, G1EagerReclaimHumongousObjects, true, EXPERIMENTAL, \ "Try to reclaim dead large objects at every young GC.") \ \ - experimental(bool, G1EagerReclaimHumongousObjectsWithStaleRefs, true, \ + product(bool, G1EagerReclaimHumongousObjectsWithStaleRefs, true, EXPERIMENTAL, \ "Try to reclaim dead large objects that have a few stale " \ "references at every young GC.") \ \ - experimental(size_t, G1RebuildRemSetChunkSize, 256 * K, \ + product(size_t, G1RebuildRemSetChunkSize, 256 * K, EXPERIMENTAL, \ "Chunk size used for rebuilding the remembered set.") \ range(4 * K, 32 * M) \ \ - experimental(uintx, G1OldCSetRegionThresholdPercent, 10, \ + product(uintx, G1OldCSetRegionThresholdPercent, 10, EXPERIMENTAL, \ "An upper bound for the number of old CSet regions expressed " \ "as a percentage of the heap size.") \ range(0, 100) \ @@ -283,17 +277,17 @@ "Force use of evacuation failure handling during mixed " \ "evacuation pauses") \ \ - diagnostic(bool, G1VerifyRSetsDuringFullGC, false, \ + product(bool, G1VerifyRSetsDuringFullGC, false, DIAGNOSTIC, \ "If true, perform verification of each heap region's " \ "remembered set when verifying the heap during a full GC.") \ \ - diagnostic(bool, G1VerifyHeapRegionCodeRoots, false, \ + product(bool, G1VerifyHeapRegionCodeRoots, false, DIAGNOSTIC, \ "Verify the code root lists attached to each heap region.") \ \ develop(bool, G1VerifyBitmaps, false, \ "Verifies the consistency of the marking bitmaps") \ \ - manageable(uintx, G1PeriodicGCInterval, 0, \ + product(uintx, G1PeriodicGCInterval, 0, MANAGEABLE, \ "Number of milliseconds after a previous GC to wait before " \ "triggering a periodic gc. A value of zero disables periodically "\ "enforced gc cycles.") \ @@ -303,21 +297,22 @@ "perform a concurrent GC as periodic GC, otherwise use a STW " \ "Full GC.") \ \ - manageable(double, G1PeriodicGCSystemLoadThreshold, 0.0, \ + product(double, G1PeriodicGCSystemLoadThreshold, 0.0, MANAGEABLE, \ "Maximum recent system wide load as returned by the 1m value " \ "of getloadavg() at which G1 triggers a periodic GC. A load " \ "above this value cancels a given periodic GC. A value of zero " \ "disables this check.") \ range(0.0, (double)max_uintx) \ \ - experimental(uintx, G1YoungExpansionBufferPercent, 10, \ + product(uintx, G1YoungExpansionBufferPercent, 10, EXPERIMENTAL, \ "When heterogenous heap is enabled by AllocateOldGenAt " \ "option, after every GC, young gen is re-sized which " \ "involves system calls to commit/uncommit memory. To " \ "reduce these calls, we keep a buffer of extra regions to " \ "absorb small changes in young gen length. This flag takes " \ "the buffer size as an percentage of young gen length") \ - range(0, 100) \ + range(0, 100) +// end of GC_G1_FLAGS #endif // SHARE_GC_G1_G1_GLOBALS_HPP diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index ce63b911dab..eadde715f6f 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -43,6 +43,7 @@ #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oop.inline.hpp" +#include "runtime/globals_extension.hpp" #include "utilities/powerOfTwo.hpp" int HeapRegion::LogOfHRGrainBytes = 0; diff --git a/src/hotspot/share/gc/g1/heapRegionManager.cpp b/src/hotspot/share/gc/g1/heapRegionManager.cpp index 15892182d29..8255be42a2e 100644 --- a/src/hotspot/share/gc/g1/heapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp @@ -85,11 +85,11 @@ HeapRegionManager* HeapRegionManager::create_manager(G1CollectedHeap* heap) { } void HeapRegionManager::initialize(G1RegionToSpaceMapper* heap_storage, - G1RegionToSpaceMapper* prev_bitmap, - G1RegionToSpaceMapper* next_bitmap, - G1RegionToSpaceMapper* bot, - G1RegionToSpaceMapper* cardtable, - G1RegionToSpaceMapper* card_counts) { + G1RegionToSpaceMapper* prev_bitmap, + G1RegionToSpaceMapper* next_bitmap, + G1RegionToSpaceMapper* bot, + G1RegionToSpaceMapper* cardtable, + G1RegionToSpaceMapper* card_counts) { _allocated_heapregions_length = 0; _heap_mapper = heap_storage; @@ -184,7 +184,8 @@ HeapRegion* HeapRegionManager::new_heap_region(uint hrm_index) { void HeapRegionManager::commit_regions(uint index, size_t num_regions, WorkGang* pretouch_gang) { guarantee(num_regions > 0, "Must commit more than zero regions"); - guarantee(_num_committed + num_regions <= max_length(), "Cannot commit more than the maximum amount of regions"); + guarantee(num_regions <= available(), + "Cannot commit more than the maximum amount of regions"); _num_committed += (uint)num_regions; @@ -321,16 +322,19 @@ void HeapRegionManager::expand_exact(uint start, uint num_regions, WorkGang* pre uint HeapRegionManager::expand_on_preferred_node(uint preferred_index) { uint expand_candidate = UINT_MAX; - for (uint i = 0; i < max_length(); i++) { - if (is_available(i)) { - // Already in use continue - continue; - } - // Always save the candidate so we can expand later on. - expand_candidate = i; - if (is_on_preferred_index(expand_candidate, preferred_index)) { - // We have found a candidate on the preffered node, break. - break; + + if (available() >= 1) { + for (uint i = 0; i < reserved_length(); i++) { + if (is_available(i)) { + // Already in use continue + continue; + } + // Always save the candidate so we can expand later on. + expand_candidate = i; + if (is_on_preferred_index(expand_candidate, preferred_index)) { + // We have found a candidate on the preferred node, break. + break; + } } } @@ -397,14 +401,18 @@ uint HeapRegionManager::find_contiguous_in_free_list(uint num_regions) { range_start = _available_map.get_next_one_offset(range_end); range_end = _available_map.get_next_zero_offset(range_start); candidate = find_contiguous_in_range((uint) range_start, (uint) range_end, num_regions); - } while (candidate == G1_NO_HRM_INDEX && range_end < max_length()); + } while (candidate == G1_NO_HRM_INDEX && range_end < reserved_length()); return candidate; } uint HeapRegionManager::find_contiguous_allow_expand(uint num_regions) { + // Check if we can actually satisfy the allocation. + if (num_regions > available()) { + return G1_NO_HRM_INDEX; + } // Find any candidate. - return find_contiguous_in_range(0, max_length(), num_regions); + return find_contiguous_in_range(0, reserved_length(), num_regions); } HeapRegion* HeapRegionManager::next_region_in_heap(const HeapRegion* r) const { @@ -420,7 +428,7 @@ HeapRegion* HeapRegionManager::next_region_in_heap(const HeapRegion* r) const { } void HeapRegionManager::iterate(HeapRegionClosure* blk) const { - uint len = max_length(); + uint len = reserved_length(); for (uint i = 0; i < len; i++) { if (!is_available(i)) { @@ -436,13 +444,13 @@ void HeapRegionManager::iterate(HeapRegionClosure* blk) const { } HeapRegionRange HeapRegionManager::find_unavailable_from_idx(uint index) const { - guarantee(index <= max_length(), "checking"); + guarantee(index <= reserved_length(), "checking"); // Find first unavailable region from offset. BitMap::idx_t start = _available_map.get_next_zero_offset(index); if (start == _available_map.size()) { // No unavailable regions found. - return HeapRegionRange(max_length(), max_length()); + return HeapRegionRange(reserved_length(), reserved_length()); } // The end of the range is the next available region. @@ -452,6 +460,8 @@ HeapRegionRange HeapRegionManager::find_unavailable_from_idx(uint index) const { assert(!_available_map.at(end - 1), "Last region (" SIZE_FORMAT ") in range is not unavailable", end - 1); assert(end == _available_map.size() || _available_map.at(end), "Region (" SIZE_FORMAT ") is not available", end); + // Shrink returned range to number of regions left to commit if necessary. + end = MIN2(start + available(), end); return HeapRegionRange((uint) start, (uint) end); } @@ -459,7 +469,7 @@ uint HeapRegionManager::find_highest_free(bool* expanded) { // Loop downwards from the highest region index, looking for an // entry which is either free or not yet committed. If not yet // committed, expand_at that index. - uint curr = max_length() - 1; + uint curr = reserved_length() - 1; while (true) { HeapRegion *hr = _regions.get_by_index(curr); if (hr == NULL || !is_available(curr)) { @@ -611,9 +621,12 @@ void HeapRegionManager::verify() { guarantee(length() <= _allocated_heapregions_length, "invariant: _length: %u _allocated_length: %u", length(), _allocated_heapregions_length); - guarantee(_allocated_heapregions_length <= max_length(), + guarantee(_allocated_heapregions_length <= reserved_length(), "invariant: _allocated_length: %u _max_length: %u", - _allocated_heapregions_length, max_length()); + _allocated_heapregions_length, reserved_length()); + guarantee(_num_committed <= max_length(), + "invariant: _num_committed: %u max_regions: %u", + _num_committed, max_length()); bool prev_committed = true; uint num_committed = 0; @@ -640,7 +653,7 @@ void HeapRegionManager::verify() { prev_committed = true; prev_end = hr->end(); } - for (uint i = _allocated_heapregions_length; i < max_length(); i++) { + for (uint i = _allocated_heapregions_length; i < reserved_length(); i++) { guarantee(_regions.get_by_index(i) == NULL, "invariant i: %u", i); } @@ -693,7 +706,7 @@ class G1RebuildFreeListTask : public AbstractGangTask { AbstractGangTask("G1 Rebuild Free List Task"), _hrm(hrm), _worker_freelists(NEW_C_HEAP_ARRAY(FreeRegionList, num_workers, mtGC)), - _worker_chunk_size((_hrm->max_length() + num_workers - 1) / num_workers), + _worker_chunk_size((_hrm->reserved_length() + num_workers - 1) / num_workers), _num_workers(num_workers) { for (uint worker = 0; worker < _num_workers; worker++) { ::new (&_worker_freelists[worker]) FreeRegionList("Appendable Worker Free List"); @@ -718,7 +731,7 @@ class G1RebuildFreeListTask : public AbstractGangTask { EventGCPhaseParallel event; uint start = worker_id * _worker_chunk_size; - uint end = MIN2(start + _worker_chunk_size, _hrm->max_length()); + uint end = MIN2(start + _worker_chunk_size, _hrm->reserved_length()); // If start is outside the heap, this worker has nothing to do. if (start > end) { diff --git a/src/hotspot/share/gc/g1/heapRegionManager.hpp b/src/hotspot/share/gc/g1/heapRegionManager.hpp index 4aad234dda1..c629b3ba562 100644 --- a/src/hotspot/share/gc/g1/heapRegionManager.hpp +++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp @@ -73,13 +73,14 @@ class HeapRegionRange : public StackObj { // region we retain the HeapRegion to be able to re-use it in the // future (in case we recommit it). // -// We keep track of three lengths: +// We keep track of four lengths: // // * _num_committed (returned by length()) is the number of currently // committed regions. These may not be contiguous. // * _allocated_heapregions_length (not exposed outside this class) is the // number of regions+1 for which we have HeapRegions. -// * max_length() returns the maximum number of regions the heap can have. +// * max_length() returns the maximum number of regions the heap may commit. +// * reserved_length() returns the maximum number of regions the heap has reserved. // class HeapRegionManager: public CHeapObj<mtGC> { @@ -94,7 +95,7 @@ class HeapRegionManager: public CHeapObj<mtGC> { // for allocation. CHeapBitMap _available_map; - // The number of regions committed in the heap. + // The number of regions committed in the heap. uint _num_committed; // Internal only. The highest heap region +1 we allocated a HeapRegion instance for. @@ -124,7 +125,7 @@ class HeapRegionManager: public CHeapObj<mtGC> { // Finds the next sequence of unavailable regions starting at the given index. Returns the // sequence found as a HeapRegionRange. If no regions can be found, both start and end of - // the returned range is equal to max_regions(). + // the returned range is equal to reserved_length(). HeapRegionRange find_unavailable_from_idx(uint index) const; // Finds the next sequence of empty regions starting from start_idx, going backwards in // the heap. Returns the length of the sequence found. If this value is zero, no @@ -240,17 +241,17 @@ class HeapRegionManager: public CHeapObj<mtGC> { return num_free_regions() * HeapRegion::GrainBytes; } - // Return the number of available (uncommitted) regions. + // Return the number of regions available (uncommitted) regions. uint available() const { return max_length() - length(); } // Return the number of regions that have been committed in the heap. uint length() const { return _num_committed; } - // Return the maximum number of regions in the heap. - uint max_length() const { return (uint)_regions.length(); } + // The number of regions reserved for the heap. + uint reserved_length() const { return (uint)_regions.length(); } // Return maximum number of regions that heap can expand to. - virtual uint max_expandable_length() const { return (uint)_regions.length(); } + virtual uint max_length() const { return reserved_length(); } MemoryUsage get_auxiliary_data_memory_usage() const; @@ -267,7 +268,7 @@ class HeapRegionManager: public CHeapObj<mtGC> { // this. virtual uint expand_at(uint start, uint num_regions, WorkGang* pretouch_workers); - // Try to expand on the given node index. + // Try to expand on the given node index, returning the index of the new region. virtual uint expand_on_preferred_node(uint node_index); HeapRegion* next_region_in_heap(const HeapRegion* r) const; diff --git a/src/hotspot/share/gc/g1/heapRegionManager.inline.hpp b/src/hotspot/share/gc/g1/heapRegionManager.inline.hpp index a72b5447c5f..e290ffb1abc 100644 --- a/src/hotspot/share/gc/g1/heapRegionManager.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegionManager.inline.hpp @@ -62,7 +62,7 @@ inline HeapRegion* HeapRegionManager::next_region_in_humongous(HeapRegion* hr) c assert(is_available(index), "pre-condition"); assert(hr->is_humongous(), "next_region_in_humongous should only be called for a humongous region."); index++; - if (index < max_length() && is_available(index) && at(index)->is_continues_humongous()) { + if (index < reserved_length() && is_available(index) && at(index)->is_continues_humongous()) { return at(index); } else { return NULL; diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index b38d9f66eab..f23932b9d0e 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp @@ -33,6 +33,7 @@ #include "memory/padded.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/debug.hpp" #include "utilities/formatBuffer.hpp" @@ -267,7 +268,7 @@ PerRegionTable* OtherRegionsTable::delete_region_table(size_t& added_by_deleted) _coarse_map.at_put(max_hrm_index, true); } else { // This will lazily initialize an uninitialized bitmap - _coarse_map.reinitialize(G1CollectedHeap::heap()->max_regions()); + _coarse_map.reinitialize(G1CollectedHeap::heap()->max_reserved_regions()); assert(!_coarse_map.at(max_hrm_index), "No coarse entries"); _coarse_map.at_put(max_hrm_index, true); // Release store guarantees that the bitmap has initialized before any diff --git a/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.cpp b/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.cpp index 69180522603..85a0af541f0 100644 --- a/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.cpp @@ -59,7 +59,7 @@ void HeterogeneousHeapRegionManager::initialize(G1RegionToSpaceMapper* heap_stor // Dram regions are committed later as needed during mutator region allocation or // when young list target length is determined after gc cycle. uint HeterogeneousHeapRegionManager::expand_by(uint num_regions, WorkGang* pretouch_workers) { - uint num_regions_possible = total_regions_committed() >= max_expandable_length() ? 0 : max_expandable_length() - total_regions_committed(); + uint num_regions_possible = total_regions_committed() >= max_length() ? 0 : max_length() - total_regions_committed(); uint num_expanded = expand_nvdimm(MIN2(num_regions, num_regions_possible), pretouch_workers); return num_expanded; } @@ -71,11 +71,11 @@ uint HeterogeneousHeapRegionManager::expand_at(uint start, uint num_regions, Wor if (num_regions == 0) { return 0; } - uint target_num_regions = MIN2(num_regions, max_expandable_length() - total_regions_committed()); + uint target_num_regions = MIN2(num_regions, max_length() - total_regions_committed()); uint end = is_in_nvdimm(start) ? end_index_of_nvdimm() : end_index_of_dram(); uint num_expanded = expand_in_range(start, end, target_num_regions, pretouch_workers); - assert(total_regions_committed() <= max_expandable_length(), "must be"); + assert(total_regions_committed() <= max_length(), "must be"); return num_expanded; } @@ -140,13 +140,13 @@ uint HeterogeneousHeapRegionManager::num_committed_nvdimm() const { } // Return maximum number of regions that heap can expand to. -uint HeterogeneousHeapRegionManager::max_expandable_length() const { +uint HeterogeneousHeapRegionManager::max_length() const { return _max_regions; } uint HeterogeneousHeapRegionManager::find_unavailable_in_range(uint start_idx, uint end_idx, uint* res_idx) const { guarantee(res_idx != NULL, "checking"); - guarantee(start_idx <= (max_length() + 1), "checking"); + guarantee(start_idx <= (reserved_length() + 1), "checking"); uint num_regions = 0; @@ -232,8 +232,8 @@ uint HeterogeneousHeapRegionManager::shrink_in_range(uint start, uint end, uint uint HeterogeneousHeapRegionManager::find_empty_in_range_reverse(uint start_idx, uint end_idx, uint* res_idx) { guarantee(res_idx != NULL, "checking"); - guarantee(start_idx < max_length(), "checking"); - guarantee(end_idx < max_length(), "checking"); + guarantee(start_idx < reserved_length(), "checking"); + guarantee(end_idx < reserved_length(), "checking"); if(start_idx > end_idx) { return 0; } @@ -385,7 +385,7 @@ uint HeterogeneousHeapRegionManager::find_contiguous(size_t start, size_t end, s "Found region sequence starting at " UINT32_FORMAT ", length " SIZE_FORMAT " that is not empty at " UINT32_FORMAT ". Hr is " PTR_FORMAT, found, num, i, p2i(hr)); } - if (!empty_only && length_unavailable > (max_expandable_length() - total_regions_committed())) { + if (!empty_only && length_unavailable > (max_length() - total_regions_committed())) { // if 'length_unavailable' number of regions will be made available, we will exceed max regions. return G1_NO_HRM_INDEX; } diff --git a/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.hpp b/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.hpp index 1e65c145396..ad4a446b6d2 100644 --- a/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.hpp +++ b/src/hotspot/share/gc/g1/heterogeneousHeapRegionManager.hpp @@ -124,7 +124,7 @@ class HeterogeneousHeapRegionManager : public HeapRegionManager { virtual HeapRegion* allocate_humongous_allow_expand(uint num_regions); // Return maximum number of regions that heap can expand to. - uint max_expandable_length() const; + uint max_length() const; // Override. Expand in nv-dimm. uint expand_by(uint num_regions, WorkGang* pretouch_workers); diff --git a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp index 9ae5782850d..27ca9c8e585 100644 --- a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp +++ b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * 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,18 +28,21 @@ #include "runtime/flags/jvmFlag.hpp" #include "utilities/globalDefinitions.hpp" -// G1 Flag Constraints -JVMFlag::Error G1RSetRegionEntriesConstraintFunc(intx value, bool verbose); -JVMFlag::Error G1RSetSparseRegionEntriesConstraintFunc(intx value, bool verbose); -JVMFlag::Error G1HeapRegionSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error G1NewSizePercentConstraintFunc(uintx value, bool verbose); -JVMFlag::Error G1MaxNewSizePercentConstraintFunc(uintx value, bool verbose); +#define G1_GC_CONSTRAINTS(f) \ + \ + /* G1 Flag Constraints */ \ + f(intx, G1RSetRegionEntriesConstraintFunc) \ + f(intx, G1RSetSparseRegionEntriesConstraintFunc) \ + f(size_t, G1HeapRegionSizeConstraintFunc) \ + f(uintx, G1NewSizePercentConstraintFunc) \ + f(uintx, G1MaxNewSizePercentConstraintFunc) \ + \ + /* G1 Subconstraints */ \ + f(uintx, MaxGCPauseMillisConstraintFuncG1) \ + f(uintx, GCPauseIntervalMillisConstraintFuncG1) \ + f(size_t, NewSizeConstraintFuncG1) -// G1 Subconstraints -JVMFlag::Error MaxGCPauseMillisConstraintFuncG1(uintx value, bool verbose); -JVMFlag::Error GCPauseIntervalMillisConstraintFuncG1(uintx value, bool verbose); -JVMFlag::Error MaxSizeForHeapAlignmentG1(const char* name, size_t value, bool verbose); -JVMFlag::Error NewSizeConstraintFuncG1(size_t value, bool verbose); +G1_GC_CONSTRAINTS(DECLARE_CONSTRAINT) size_t MaxSizeForHeapAlignmentG1(); diff --git a/src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.hpp b/src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.hpp index cc35f62e9b9..2b5c79322e4 100644 --- a/src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.hpp +++ b/src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,11 @@ #include "utilities/globalDefinitions.hpp" // Parallel Subconstraints -JVMFlag::Error ParallelGCThreadsConstraintFuncParallel(uint value, bool verbose); -JVMFlag::Error InitialTenuringThresholdConstraintFuncParallel(uintx value, bool verbose); -JVMFlag::Error MaxTenuringThresholdConstraintFuncParallel(uintx value, bool verbose); +#define PARALLEL_GC_CONSTRAINTS(f) \ + f(uint, ParallelGCThreadsConstraintFuncParallel) \ + f(uintx, InitialTenuringThresholdConstraintFuncParallel) \ + f(uintx, MaxTenuringThresholdConstraintFuncParallel) + +PARALLEL_GC_CONSTRAINTS(DECLARE_CONSTRAINT) #endif // SHARE_GC_PARALLEL_JVMFLAGCONSTRAINTSPARALLEL_HPP diff --git a/src/hotspot/share/gc/parallel/parallel_globals.hpp b/src/hotspot/share/gc/parallel/parallel_globals.hpp index f949fa5f133..19953ca0b61 100644 --- a/src/hotspot/share/gc/parallel/parallel_globals.hpp +++ b/src/hotspot/share/gc/parallel/parallel_globals.hpp @@ -29,13 +29,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ product(uintx, HeapMaximumCompactionInterval, 20, \ @@ -67,4 +61,6 @@ product(bool, PSChunkLargeArrays, true, \ "Process large arrays in chunks") +// end of GC_PARALLEL_FLAGS + #endif // SHARE_GC_PARALLEL_PARALLEL_GLOBALS_HPP diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 1a11abb2614..83a5e1f6412 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -931,11 +931,7 @@ HeapWord* DefNewGeneration::allocate(size_t word_size, bool is_tlab) { // Note that since DefNewGeneration supports lock-free allocation, we // have to use it here, as well. HeapWord* result = eden()->par_allocate(word_size); - if (result != NULL) { - if (_old_gen != NULL) { - _old_gen->sample_eden_chunk(); - } - } else { + if (result == NULL) { // If the eden is full and the last collection bailed out, we are running // out of heap space, and we try to allocate the from-space, too. // allocate_from_space can't be inlined because that would introduce a @@ -947,11 +943,7 @@ HeapWord* DefNewGeneration::allocate(size_t word_size, bool is_tlab) { HeapWord* DefNewGeneration::par_allocate(size_t word_size, bool is_tlab) { - HeapWord* res = eden()->par_allocate(word_size); - if (_old_gen != NULL) { - _old_gen->sample_eden_chunk(); - } - return res; + return eden()->par_allocate(word_size); } size_t DefNewGeneration::tlab_capacity() const { diff --git a/src/hotspot/share/gc/serial/serial_globals.hpp b/src/hotspot/share/gc/serial/serial_globals.hpp index 4da44ff2c55..91a9d8c52b9 100644 --- a/src/hotspot/share/gc/serial/serial_globals.hpp +++ b/src/hotspot/share/gc/serial/serial_globals.hpp @@ -25,18 +25,14 @@ #ifndef SHARE_GC_SERIAL_SERIAL_GLOBALS_HPP #define SHARE_GC_SERIAL_SERIAL_GLOBALS_HPP -#define GC_SERIAL_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ - notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ - range, \ +#define GC_SERIAL_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ constraint) +// end of GC_SERIAL_FLAGS + #endif // SHARE_GC_SERIAL_SERIAL_GLOBALS_HPP diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp index 34b74c951df..ebe04a23b23 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,7 +187,7 @@ void CardTableBarrierSet::on_thread_detach(Thread* thread) { // card-table (or other remembered set structure) before GC starts // processing the card-table (or other remembered set). if (thread->is_Java_thread()) { // Only relevant for Java threads. - flush_deferred_card_mark_barrier((JavaThread*)thread); + flush_deferred_card_mark_barrier(thread->as_Java_thread()); } } diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 22ccd8c5f57..2e41655da99 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -36,6 +36,7 @@ #include "gc/shared/gcWhen.hpp" #include "gc/shared/memAllocator.hpp" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/metaspace.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" @@ -123,14 +124,28 @@ MetaspaceSummary CollectedHeap::create_metaspace_summary() { } void CollectedHeap::print_heap_before_gc() { - Universe::print_heap_before_gc(); + LogTarget(Debug, gc, heap) lt; + if (lt.is_enabled()) { + LogStream ls(lt); + ls.print_cr("Heap before GC invocations=%u (full %u):", total_collections(), total_full_collections()); + ResourceMark rm; + print_on(&ls); + } + if (_gc_heap_log != NULL) { _gc_heap_log->log_heap_before(this); } } void CollectedHeap::print_heap_after_gc() { - Universe::print_heap_after_gc(); + LogTarget(Debug, gc, heap) lt; + if (lt.is_enabled()) { + LogStream ls(lt); + ls.print_cr("Heap after GC invocations=%u (full %u):", total_collections(), total_full_collections()); + ResourceMark rm; + print_on(&ls); + } + if (_gc_heap_log != NULL) { _gc_heap_log->log_heap_after(this); } diff --git a/src/hotspot/share/gc/shared/gcConfiguration.cpp b/src/hotspot/share/gc/shared/gcConfiguration.cpp index 2a24e031b9c..195b64dcc3c 100644 --- a/src/hotspot/share/gc/shared/gcConfiguration.cpp +++ b/src/hotspot/share/gc/shared/gcConfiguration.cpp @@ -22,6 +22,7 @@ * */ #include "precompiled.hpp" +#include "runtime/globals_extension.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcArguments.hpp" diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 811cfa3da51..956634b2066 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -50,13 +50,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ @@ -65,13 +59,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint)) \ \ @@ -80,13 +68,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint)) \ \ @@ -95,13 +77,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint)) \ \ @@ -110,13 +86,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint)) \ \ @@ -125,13 +95,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint)) \ \ @@ -140,13 +104,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint)) \ \ @@ -161,7 +119,7 @@ product(bool, UseParallelGC, false, \ "Use the Parallel garbage collector.") \ \ - experimental(bool, UseEpsilonGC, false, \ + product(bool, UseEpsilonGC, false, EXPERIMENTAL, \ "Use the Epsilon (no-op) garbage collector") \ \ product(bool, UseZGC, false, \ @@ -179,14 +137,14 @@ "ParallelGCThreads parallel collectors will use for garbage " \ "collection work") \ \ - diagnostic(bool, InjectGCWorkerCreationFailure, false, \ + product(bool, InjectGCWorkerCreationFailure, false, DIAGNOSTIC, \ "Inject thread creation failures for " \ "UseDynamicNumberOfGCThreads") \ \ product(size_t, HeapSizePerGCThread, ScaleForWordSize(32*M), \ "Size of heap (bytes) per GC thread used in calculating the " \ "number of GC threads") \ - range((size_t)os::vm_page_size(), (size_t)max_uintx) \ + constraint(VMPageSizeConstraintFunc, AtParse) \ \ product(uint, ConcGCThreads, 0, \ "Number of threads concurrent gc will use") \ @@ -211,7 +169,7 @@ "is active (as a percentage)") \ range(0, 100) \ \ - diagnostic(uintx, GCLockerRetryAllocationCount, 2, \ + product(uintx, GCLockerRetryAllocationCount, 2, DIAGNOSTIC, \ "Number of times to retry allocations when " \ "blocked by the GC locker") \ range(0, max_uintx) \ @@ -268,7 +226,7 @@ product(bool, ParallelRefProcBalancingEnabled, true, \ "Enable balancing of reference processing queues") \ \ - experimental(size_t, ReferencesPerThread, 1000, \ + product(size_t, ReferencesPerThread, 1000, EXPERIMENTAL, \ "Ergonomically start one thread for this amount of " \ "references for reference processing if " \ "ParallelRefProcEnabled is true. Specify 0 to disable and " \ @@ -308,17 +266,17 @@ develop(uintx, PromotionFailureALotInterval, 5, \ "Total collections between promotion failures a lot") \ \ - experimental(uintx, WorkStealingSleepMillis, 1, \ + product(uintx, WorkStealingSleepMillis, 1, EXPERIMENTAL, \ "Sleep time when sleep is used for yields") \ \ - experimental(uintx, WorkStealingYieldsBeforeSleep, 5000, \ + product(uintx, WorkStealingYieldsBeforeSleep, 5000, EXPERIMENTAL, \ "Number of yields before a sleep is done during work stealing") \ \ - experimental(uintx, WorkStealingHardSpins, 4096, \ + product(uintx, WorkStealingHardSpins, 4096, EXPERIMENTAL, \ "Number of iterations in a spin loop between checks on " \ "time out of hard spin") \ \ - experimental(uintx, WorkStealingSpinToYieldRatio, 10, \ + product(uintx, WorkStealingSpinToYieldRatio, 10, EXPERIMENTAL, \ "Ratio of hard spins to calls to yield") \ \ develop(uintx, ObjArrayMarkingStride, 2048, \ @@ -563,27 +521,27 @@ "How many fields ahead to prefetch in oop scan (<= 0 means off)") \ range(-1, max_jint) \ \ - diagnostic(bool, VerifyDuringStartup, false, \ + product(bool, VerifyDuringStartup, false, DIAGNOSTIC, \ "Verify memory system before executing any Java code " \ "during VM initialization") \ \ - diagnostic(bool, VerifyBeforeExit, trueInDebug, \ + product(bool, VerifyBeforeExit, trueInDebug, DIAGNOSTIC, \ "Verify system before exiting") \ \ - diagnostic(bool, VerifyBeforeGC, false, \ + product(bool, VerifyBeforeGC, false, DIAGNOSTIC, \ "Verify memory system before GC") \ \ - diagnostic(bool, VerifyAfterGC, false, \ + product(bool, VerifyAfterGC, false, DIAGNOSTIC, \ "Verify memory system after GC") \ \ - diagnostic(bool, VerifyDuringGC, false, \ + product(bool, VerifyDuringGC, false, DIAGNOSTIC, \ "Verify memory system during GC (between phases)") \ \ - diagnostic(ccstrlist, VerifyGCType, "", \ + product(ccstrlist, VerifyGCType, "", DIAGNOSTIC, \ "GC type(s) to verify when Verify*GC is enabled." \ "Available types are collector specific.") \ \ - diagnostic(ccstrlist, VerifySubSet, "", \ + product(ccstrlist, VerifySubSet, "", DIAGNOSTIC, \ "Memory sub-systems to verify when Verify*GC flag(s) " \ "are enabled. One or more sub-systems can be specified " \ "in a comma separated string. Sub-systems are: " \ @@ -591,20 +549,20 @@ "dictionary, classloader_data_graph, metaspace, jni_handles, " \ "codecache_oops") \ \ - diagnostic(bool, GCParallelVerificationEnabled, true, \ + product(bool, GCParallelVerificationEnabled, true, DIAGNOSTIC, \ "Enable parallel memory system verification") \ \ - diagnostic(bool, DeferInitialCardMark, false, \ + product(bool, DeferInitialCardMark, false, DIAGNOSTIC, \ "When +ReduceInitialCardMarks, explicitly defer any that " \ "may arise from new_pre_store_barrier") \ \ product(bool, UseCondCardMark, false, \ "Check for already marked card before updating card table") \ \ - diagnostic(bool, VerifyRememberedSets, false, \ + product(bool, VerifyRememberedSets, false, DIAGNOSTIC, \ "Verify GC remembered sets") \ \ - diagnostic(bool, VerifyObjectStartArray, true, \ + product(bool, VerifyObjectStartArray, true, DIAGNOSTIC, \ "Verify GC object start array if verify before/after") \ \ product(bool, DisableExplicitGC, false, \ @@ -649,7 +607,7 @@ "Maximum heap size (in bytes)") \ constraint(MaxHeapSizeConstraintFunc,AfterErgo) \ \ - manageable(size_t, SoftMaxHeapSize, 0, \ + product(size_t, SoftMaxHeapSize, 0, MANAGEABLE, \ "Soft limit for maximum heap size (in bytes)") \ constraint(SoftMaxHeapSizeConstraintFunc,AfterMemoryInit) \ \ @@ -730,11 +688,11 @@ "will retry before printing a warning") \ range(0, max_uintx) \ \ - diagnostic(uintx, VerifyGCStartAt, 0, \ + product(uintx, VerifyGCStartAt, 0, DIAGNOSTIC, \ "GC invoke count where +VerifyBefore/AfterGC kicks in") \ range(0, max_uintx) \ \ - diagnostic(intx, VerifyGCLevel, 0, \ + product(intx, VerifyGCLevel, 0, DIAGNOSTIC, \ "Generation level at which to start +VerifyBefore/AfterGC") \ range(0, 1) \ \ @@ -775,4 +733,6 @@ "during parallel gc") \ range(0, max_juint) +// end of GC_FLAGS + #endif // SHARE_GC_SHARED_GC_GLOBALS_HPP diff --git a/src/hotspot/share/gc/shared/generation.hpp b/src/hotspot/share/gc/shared/generation.hpp index 539e6675fc2..9643dd74db1 100644 --- a/src/hotspot/share/gc/shared/generation.hpp +++ b/src/hotspot/share/gc/shared/generation.hpp @@ -371,17 +371,6 @@ class Generation: public CHeapObj<mtGC> { virtual void post_compact() { ShouldNotReachHere(); } #endif - // Support for CMS's rescan. In this general form we return a pointer - // to an abstract object that can be used, based on specific previously - // decided protocols, to exchange information between generations, - // information that may be useful for speeding up certain types of - // garbage collectors. A NULL value indicates to the client that - // no data recording is expected by the provider. The data-recorder is - // expected to be GC worker thread-local, with the worker index - // indicated by "thr_num". - virtual void* get_data_recorder(int thr_num) { return NULL; } - virtual void sample_eden_chunk() {} - // Some generations may require some cleanup actions before allowing // a verification. virtual void prepare_for_verify() {} diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp index 12602a19fee..f2962b41c63 100644 --- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp +++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,38 +40,44 @@ * whenever flag's value changes. If the constraint fails the function should return * an appropriate error value. */ +#define SHARED_GC_CONSTRAINTS(f) \ + f(uint, ParallelGCThreadsConstraintFunc) \ + f(uint, ConcGCThreadsConstraintFunc) \ + f(size_t, YoungPLABSizeConstraintFunc) \ + f(size_t, OldPLABSizeConstraintFunc) \ + f(uintx, MinHeapFreeRatioConstraintFunc) \ + f(uintx, MaxHeapFreeRatioConstraintFunc) \ + f(intx, SoftRefLRUPolicyMSPerMBConstraintFunc) \ + f(size_t, MarkStackSizeConstraintFunc) \ + f(uintx, MinMetaspaceFreeRatioConstraintFunc) \ + f(uintx, MaxMetaspaceFreeRatioConstraintFunc) \ + f(uintx, InitialTenuringThresholdConstraintFunc) \ + f(uintx, MaxTenuringThresholdConstraintFunc) \ + \ + f(uintx, MaxGCPauseMillisConstraintFunc) \ + f(uintx, GCPauseIntervalMillisConstraintFunc) \ + f(size_t, InitialBootClassLoaderMetaspaceSizeConstraintFunc) \ + f(size_t, MinHeapSizeConstraintFunc) \ + f(size_t, InitialHeapSizeConstraintFunc) \ + f(size_t, MaxHeapSizeConstraintFunc) \ + f(size_t, SoftMaxHeapSizeConstraintFunc) \ + f(size_t, HeapBaseMinAddressConstraintFunc) \ + f(size_t, NewSizeConstraintFunc) \ + f(size_t, MinTLABSizeConstraintFunc) \ + f(size_t, TLABSizeConstraintFunc) \ + f(uintx, TLABWasteIncrementConstraintFunc) \ + f(uintx, SurvivorRatioConstraintFunc) \ + f(size_t, MetaspaceSizeConstraintFunc) \ + f(size_t, MaxMetaspaceSizeConstraintFunc) \ + f(intx, SurvivorAlignmentInBytesConstraintFunc) -JVMFlag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose); -JVMFlag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose); -JVMFlag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose); -JVMFlag::Error MaxHeapFreeRatioConstraintFunc(uintx value, bool verbose); -JVMFlag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose); -JVMFlag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose); -JVMFlag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose); -JVMFlag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose); -JVMFlag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose); +SHARED_GC_CONSTRAINTS(DECLARE_CONSTRAINT) -JVMFlag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose); -JVMFlag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose); -JVMFlag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error MinHeapSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error SoftMaxHeapSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose); -JVMFlag::Error NewSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error TLABSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error TLABWasteIncrementConstraintFunc(uintx value, bool verbose); -JVMFlag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose); -JVMFlag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose); -JVMFlag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose); - -// Internal JVMFlag::Error MaxPLABSizeBounds(const char* name, size_t value, bool verbose); +#define GC_CONSTRAINTS(f) \ + SHARED_GC_CONSTRAINTS(f) \ + G1GC_ONLY(G1_GC_CONSTRAINTS(f)) \ + PARALLELGC_ONLY(PARALLEL_GC_CONSTRAINTS(f)) + #endif // SHARE_GC_SHARED_JVMFLAGCONSTRAINTSGC_HPP diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index 312050b4098..e20f77e0ebe 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -113,8 +113,8 @@ class TaskQueueSuper: public CHeapObj<F> { // N must be a power of 2 for computing modulo via masking. // N must be >= 2 for the algorithm to work at all, though larger is better. - // C++11: is_power_of_2 is not (yet) constexpr. - STATIC_ASSERT((N >= 2) && ((N & (N - 1)) == 0)); + STATIC_ASSERT(N >= 2); + STATIC_ASSERT(is_power_of_2(N)); static const uint MOD_N_MASK = N - 1; class Age { diff --git a/src/hotspot/share/gc/shared/workerPolicy.cpp b/src/hotspot/share/gc/shared/workerPolicy.cpp index 76f80dc1396..8116265bd01 100644 --- a/src/hotspot/share/gc/shared/workerPolicy.cpp +++ b/src/hotspot/share/gc/shared/workerPolicy.cpp @@ -27,6 +27,7 @@ #include "gc/shared/workerPolicy.hpp" #include "logging/log.hpp" #include "memory/universe.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/os.inline.hpp" #include "runtime/vm_version.hpp" diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp index b64bf975ad6..4ce2366fe0c 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp @@ -23,7 +23,6 @@ */ #include "precompiled.hpp" - #include "gc/shared/gcCause.hpp" #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" @@ -33,6 +32,7 @@ #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "logging/log.hpp" #include "logging/logTag.hpp" +#include "runtime/globals_extension.hpp" int ShenandoahHeuristics::compare_by_garbage(RegionData a, RegionData b) { if (a._garbage > b._garbage) diff --git a/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp b/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp index 78564bd45e1..ca221567b2c 100644 --- a/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp +++ b/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp @@ -31,6 +31,7 @@ #include "gc/shenandoah/mode/shenandoahIUMode.hpp" #include "logging/log.hpp" #include "logging/logTag.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" void ShenandoahIUMode::initialize_flags() const { diff --git a/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp b/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp index 1d5005f70b4..bb7d0c4660b 100644 --- a/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp +++ b/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp @@ -27,6 +27,7 @@ #include "gc/shenandoah/mode/shenandoahPassiveMode.hpp" #include "logging/log.hpp" #include "logging/logTag.hpp" +#include "runtime/globals_extension.hpp" void ShenandoahPassiveMode::initialize_flags() const { // Do not allow concurrent cycles. diff --git a/src/hotspot/share/gc/shenandoah/mode/shenandoahSATBMode.cpp b/src/hotspot/share/gc/shenandoah/mode/shenandoahSATBMode.cpp index c6e7c8fc6a8..020df4b581a 100644 --- a/src/hotspot/share/gc/shenandoah/mode/shenandoahSATBMode.cpp +++ b/src/hotspot/share/gc/shenandoah/mode/shenandoahSATBMode.cpp @@ -31,6 +31,7 @@ #include "gc/shenandoah/mode/shenandoahSATBMode.hpp" #include "logging/log.hpp" #include "logging/logTag.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" void ShenandoahSATBMode::initialize_flags() const { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp index d146214f517..f0733a6fa45 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -29,6 +29,7 @@ #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "utilities/defaultStream.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index 108952fa0e9..891ccfe93d6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -206,8 +206,7 @@ class ShenandoahSATBAndRemarkCodeRootsThreadsClosure : public ThreadClosure { // * Weakly reachable otherwise // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be // live by the SATB invariant but other oops recorded in nmethods may behave differently. - JavaThread* jt = (JavaThread*)thread; - jt->nmethods_do(_code_cl); + thread->as_Java_thread()->nmethods_do(_code_cl); } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index ea7cafbcd68..7df181fa2ca 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -2162,10 +2162,11 @@ bool ShenandoahHeap::try_cancel_gc() { else if (prev == CANCELLED) return false; assert(ShenandoahSuspendibleWorkers, "should not get here when not using suspendible workers"); assert(prev == NOT_CANCELLED, "must be NOT_CANCELLED"); - if (Thread::current()->is_Java_thread()) { + Thread* thread = Thread::current(); + if (thread->is_Java_thread()) { // We need to provide a safepoint here, otherwise we might // spin forever if a SP is pending. - ThreadBlockInVM sp(JavaThread::current()); + ThreadBlockInVM sp(thread->as_Java_thread()); SpinPause(); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index d50353eb455..2dd5f161d1d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -35,6 +35,7 @@ #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index 39d7d2a9056..39470c1af2f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -24,9 +24,7 @@ #include "precompiled.hpp" -#include "classfile/classLoaderDataGraph.hpp" -#include "classfile/stringTable.hpp" -#include "code/codeCache.hpp" +#include "classfile/classLoaderData.hpp" #include "code/nmethod.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahConcurrentRoots.hpp" @@ -34,7 +32,6 @@ #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" -#include "gc/shenandoah/shenandoahVMOperations.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "runtime/thread.hpp" @@ -209,7 +206,6 @@ void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops, CLDClosur "Expect class unloading when Shenandoah cycle is running"); assert(clds != NULL, "Only possible with CLD closure"); - AlwaysTrueClosure always_true; ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); ResourceMark rm; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp index 592652440a3..883e8229961 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp @@ -26,8 +26,6 @@ #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP #include "classfile/classLoaderDataGraph.hpp" -#include "classfile/stringTable.hpp" -#include "classfile/systemDictionary.hpp" #include "gc/shared/oopStorageSetParState.inline.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahConcurrentRoots.hpp" @@ -37,7 +35,6 @@ #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "memory/resourceArea.hpp" -#include "prims/resolvedMethodTable.hpp" #include "runtime/safepoint.hpp" template <bool CONCURRENT> diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.cpp b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.cpp index c62407d47fd..b9e47394200 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.cpp @@ -50,7 +50,7 @@ ShenandoahStrDedupQueue::ShenandoahStrDedupQueue() : ShenandoahStrDedupQueue::~ShenandoahStrDedupQueue() { MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag); - for (size_t index = 0; index < num_queues(); index ++) { + for (size_t index = 0; index < num_queues_nv(); index ++) { release_buffers(queue_at(index)); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.hpp index ca373f85c0a..1aa6d91971e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.hpp @@ -99,9 +99,11 @@ class ShenandoahStrDedupQueue : public StringDedupQueue { void verify_impl(); protected: - size_t num_queues() const { return (_num_producer_queue + 2); } + size_t num_queues() const { return num_queues_nv(); } private: + inline size_t num_queues_nv() const { return (_num_producer_queue + 2); } + ShenandoahQueueBuffer* new_buffer(); void release_buffers(ShenandoahQueueBuffer* list); @@ -111,8 +113,6 @@ class ShenandoahStrDedupQueue : public StringDedupQueue { bool pop_candidate(oop& obj); void set_producer_buffer(ShenandoahQueueBuffer* buf, size_t queue_id); - - void verify(ShenandoahQueueBuffer* head); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSTRDEDUPQUEUE_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index 31d2c5382b1..98aa933e01c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -30,33 +30,27 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ - experimental(size_t, ShenandoahRegionSize, 0, \ + product(size_t, ShenandoahRegionSize, 0, EXPERIMENTAL, \ "Static heap region size. Set zero to enable automatic sizing.") \ \ - experimental(size_t, ShenandoahTargetNumRegions, 2048, \ + product(size_t, ShenandoahTargetNumRegions, 2048, EXPERIMENTAL, \ "With automatic region sizing, this is the approximate number " \ "of regions that would be used, within min/max region size " \ "limits.") \ \ - experimental(size_t, ShenandoahMinRegionSize, 256 * K, \ + product(size_t, ShenandoahMinRegionSize, 256 * K, EXPERIMENTAL, \ "With automatic region sizing, the regions would be at least " \ "this large.") \ \ - experimental(size_t, ShenandoahMaxRegionSize, 32 * M, \ + product(size_t, ShenandoahMaxRegionSize, 32 * M, EXPERIMENTAL, \ "With automatic region sizing, the regions would be at most " \ "this large.") \ \ - experimental(intx, ShenandoahHumongousThreshold, 100, \ + product(intx, ShenandoahHumongousThreshold, 100, EXPERIMENTAL, \ "Humongous objects are allocated in separate regions. " \ "This setting defines how large the object should be to be " \ "deemed humongous. Value is in percents of heap region size. " \ @@ -82,19 +76,19 @@ " compact - run GC more frequently and with deeper targets to " \ "free up more memory.") \ \ - experimental(uintx, ShenandoahRefProcFrequency, 5, \ + product(uintx, ShenandoahRefProcFrequency, 5, EXPERIMENTAL, \ "Process process weak (soft, phantom, finalizers) references " \ "every Nth cycle. Normally affects concurrent GC cycles only, " \ "as degenerated and full GCs would try to process references " \ "regardless. Set to zero to disable reference processing " \ "completely.") \ \ - experimental(uintx, ShenandoahUnloadClassesFrequency, 1, \ + product(uintx, ShenandoahUnloadClassesFrequency, 1, EXPERIMENTAL, \ "Unload the classes every Nth cycle. Normally affects concurrent "\ "GC cycles, as degenerated and full GCs would try to unload " \ "classes regardless. Set to zero to disable class unloading.") \ \ - experimental(uintx, ShenandoahGarbageThreshold, 25, \ + product(uintx, ShenandoahGarbageThreshold, 25, EXPERIMENTAL, \ "How much garbage a region has to contain before it would be " \ "taken for collection. This a guideline only, as GC heuristics " \ "may select the region for collection even if it has little " \ @@ -102,63 +96,63 @@ "collector accepts. In percents of heap region size.") \ range(0,100) \ \ - experimental(uintx, ShenandoahInitFreeThreshold, 70, \ + product(uintx, ShenandoahInitFreeThreshold, 70, EXPERIMENTAL, \ "How much heap should be free before some heuristics trigger the "\ "initial (learning) cycles. Affects cycle frequency on startup " \ "and after drastic state changes, e.g. after degenerated/full " \ "GC cycles. In percents of (soft) max heap size.") \ range(0,100) \ \ - experimental(uintx, ShenandoahMinFreeThreshold, 10, \ + product(uintx, ShenandoahMinFreeThreshold, 10, EXPERIMENTAL, \ "How much heap should be free before most heuristics trigger the "\ "collection, even without other triggers. Provides the safety " \ "margin for many heuristics. In percents of (soft) max heap size.")\ range(0,100) \ \ - experimental(uintx, ShenandoahAllocationThreshold, 0, \ + product(uintx, ShenandoahAllocationThreshold, 0, EXPERIMENTAL, \ "How many new allocations should happen since the last GC cycle " \ "before some heuristics trigger the collection. In percents of " \ "(soft) max heap size. Set to zero to effectively disable.") \ range(0,100) \ \ - experimental(uintx, ShenandoahAllocSpikeFactor, 5, \ + product(uintx, ShenandoahAllocSpikeFactor, 5, EXPERIMENTAL, \ "How much of heap should some heuristics reserve for absorbing " \ "the allocation spikes. Larger value wastes more memory in " \ "non-emergency cases, but provides more safety in emergency " \ "cases. In percents of (soft) max heap size.") \ range(0,100) \ \ - experimental(uintx, ShenandoahLearningSteps, 5, \ + product(uintx, ShenandoahLearningSteps, 5, EXPERIMENTAL, \ "The number of cycles some heuristics take to collect in order " \ "to learn application and GC performance.") \ range(0,100) \ \ - experimental(uintx, ShenandoahImmediateThreshold, 90, \ + product(uintx, ShenandoahImmediateThreshold, 90, EXPERIMENTAL, \ "The cycle may shortcut when enough garbage can be reclaimed " \ "from the immediate garbage (completely garbage regions). " \ "In percents of total garbage found. Setting this threshold " \ "to 100 effectively disables the shortcut.") \ range(0,100) \ \ - experimental(uintx, ShenandoahGuaranteedGCInterval, 5*60*1000, \ + product(uintx, ShenandoahGuaranteedGCInterval, 5*60*1000, EXPERIMENTAL, \ "Many heuristics would guarantee a concurrent GC cycle at " \ "least with this interval. This is useful when large idle " \ "intervals are present, where GC can run without stealing " \ "time from active application. Time is in milliseconds. " \ "Setting this to 0 disables the feature.") \ \ - experimental(bool, ShenandoahAlwaysClearSoftRefs, false, \ + product(bool, ShenandoahAlwaysClearSoftRefs, false, EXPERIMENTAL, \ "Unconditionally clear soft references, instead of using any " \ "other cleanup policy. This minimizes footprint at expense of" \ "more soft reference churn in applications.") \ \ - experimental(bool, ShenandoahUncommit, true, \ + product(bool, ShenandoahUncommit, true, EXPERIMENTAL, \ "Allow to uncommit memory under unused regions and metadata. " \ "This optimizes footprint at expense of allocation latency in " \ "regions that require committing back. Uncommits would be " \ "disabled by some heuristics, or with static heap size.") \ \ - experimental(uintx, ShenandoahUncommitDelay, 5*60*1000, \ + product(uintx, ShenandoahUncommitDelay, 5*60*1000, EXPERIMENTAL, \ "Uncommit memory for regions that were not used for more than " \ "this time. First use after that would incur allocation stalls. " \ "Actively used regions would never be uncommitted, because they " \ @@ -166,37 +160,37 @@ "milliseconds. Setting this delay to 0 effectively uncommits " \ "regions almost immediately after they become unused.") \ \ - experimental(bool, ShenandoahRegionSampling, false, \ + product(bool, ShenandoahRegionSampling, false, EXPERIMENTAL, \ "Provide heap region sampling data via jvmstat.") \ \ - experimental(int, ShenandoahRegionSamplingRate, 40, \ + product(int, ShenandoahRegionSamplingRate, 40, EXPERIMENTAL, \ "Sampling rate for heap region sampling. In milliseconds between "\ "the samples. Higher values provide more fidelity, at expense " \ "of more sampling overhead.") \ \ - experimental(uintx, ShenandoahControlIntervalMin, 1, \ + product(uintx, ShenandoahControlIntervalMin, 1, EXPERIMENTAL, \ "The minimum sleep interval for the control loop that drives " \ "the cycles. Lower values would increase GC responsiveness " \ "to changing heap conditions, at the expense of higher perf " \ "overhead. Time is in milliseconds.") \ \ - experimental(uintx, ShenandoahControlIntervalMax, 10, \ + product(uintx, ShenandoahControlIntervalMax, 10, EXPERIMENTAL, \ "The maximum sleep interval for control loop that drives " \ "the cycles. Lower values would increase GC responsiveness " \ "to changing heap conditions, at the expense of higher perf " \ "overhead. Time is in milliseconds.") \ \ - experimental(uintx, ShenandoahControlIntervalAdjustPeriod, 1000, \ + product(uintx, ShenandoahControlIntervalAdjustPeriod, 1000, EXPERIMENTAL, \ "The time period for one step in control loop interval " \ "adjustment. Lower values make adjustments faster, at the " \ "expense of higher perf overhead. Time is in milliseconds.") \ \ - diagnostic(bool, ShenandoahVerify, false, \ + product(bool, ShenandoahVerify, false, DIAGNOSTIC, \ "Enable internal verification. This would catch many GC bugs, " \ "but it would also stall the collector during the verification, " \ "which prolongs the pauses and might hide other bugs.") \ \ - diagnostic(intx, ShenandoahVerifyLevel, 4, \ + product(intx, ShenandoahVerifyLevel, 4, DIAGNOSTIC, \ "Verification level, higher levels check more, taking more time. "\ "Accepted values are:" \ " 0 = basic heap checks; " \ @@ -205,34 +199,34 @@ " 3 = previous level, plus all reachable objects; " \ " 4 = previous level, plus all marked objects") \ \ - diagnostic(bool, ShenandoahElasticTLAB, true, \ + product(bool, ShenandoahElasticTLAB, true, DIAGNOSTIC, \ "Use Elastic TLABs with Shenandoah") \ \ - experimental(uintx, ShenandoahEvacReserve, 5, \ + product(uintx, ShenandoahEvacReserve, 5, EXPERIMENTAL, \ "How much of heap to reserve for evacuations. Larger values make "\ "GC evacuate more live objects on every cycle, while leaving " \ "less headroom for application to allocate in. In percents of " \ "total heap size.") \ range(1,100) \ \ - experimental(double, ShenandoahEvacWaste, 1.2, \ + product(double, ShenandoahEvacWaste, 1.2, EXPERIMENTAL, \ "How much waste evacuations produce within the reserved space. " \ "Larger values make evacuations more resilient against " \ "evacuation conflicts, at expense of evacuating less on each " \ "GC cycle.") \ range(1.0,100.0) \ \ - experimental(bool, ShenandoahEvacReserveOverflow, true, \ + product(bool, ShenandoahEvacReserveOverflow, true, EXPERIMENTAL, \ "Allow evacuations to overflow the reserved space. Enabling it " \ "will make evacuations more resilient when evacuation " \ "reserve/waste is incorrect, at the risk that application " \ "runs out of memory too early.") \ \ - experimental(bool, ShenandoahPacing, true, \ + product(bool, ShenandoahPacing, true, EXPERIMENTAL, \ "Pace application allocations to give GC chance to start " \ "and complete before allocation failure is reached.") \ \ - experimental(uintx, ShenandoahPacingMaxDelay, 10, \ + product(uintx, ShenandoahPacingMaxDelay, 10, EXPERIMENTAL, \ "Max delay for pacing application allocations. Larger values " \ "provide more resilience against out of memory, at expense at " \ "hiding the GC latencies in the allocation path. Time is in " \ @@ -240,7 +234,7 @@ "GC effectively stall the threads indefinitely instead of going " \ "to degenerated or Full GC.") \ \ - experimental(uintx, ShenandoahPacingIdleSlack, 2, \ + product(uintx, ShenandoahPacingIdleSlack, 2, EXPERIMENTAL, \ "How much of heap counted as non-taxable allocations during idle "\ "phases. Larger value makes the pacing milder when collector is " \ "idle, requiring less rendezvous with control thread. Lower " \ @@ -248,101 +242,101 @@ "allocs. In percent of total heap size.") \ range(0, 100) \ \ - experimental(uintx, ShenandoahPacingCycleSlack, 10, \ + product(uintx, ShenandoahPacingCycleSlack, 10, EXPERIMENTAL, \ "How much of free space to take as non-taxable allocations " \ "the GC cycle. Larger value makes the pacing milder at the " \ "beginning of the GC cycle. Lower value makes the pacing less " \ "uniform during the cycle. In percent of free space.") \ range(0, 100) \ \ - experimental(double, ShenandoahPacingSurcharge, 1.1, \ + product(double, ShenandoahPacingSurcharge, 1.1, EXPERIMENTAL, \ "Additional pacing tax surcharge to help unclutter the heap. " \ "Larger values makes the pacing more aggressive. Lower values " \ "risk GC cycles finish with less memory than were available at " \ "the beginning of it.") \ range(1.0, 100.0) \ \ - experimental(uintx, ShenandoahCriticalFreeThreshold, 1, \ + product(uintx, ShenandoahCriticalFreeThreshold, 1, EXPERIMENTAL, \ "How much of the heap needs to be free after recovery cycles, " \ "either Degenerated or Full GC to be claimed successful. If this "\ "much space is not available, next recovery step would be " \ "triggered.") \ range(0, 100) \ \ - diagnostic(bool, ShenandoahDegeneratedGC, true, \ + product(bool, ShenandoahDegeneratedGC, true, DIAGNOSTIC, \ "Enable Degenerated GC as the graceful degradation step. " \ "Disabling this option leads to degradation to Full GC instead. " \ "When running in passive mode, this can be toggled to measure " \ "either Degenerated GC or Full GC costs.") \ \ - experimental(uintx, ShenandoahFullGCThreshold, 3, \ + product(uintx, ShenandoahFullGCThreshold, 3, EXPERIMENTAL, \ "How many back-to-back Degenerated GCs should happen before " \ "going to a Full GC.") \ \ - experimental(bool, ShenandoahImplicitGCInvokesConcurrent, false, \ + product(bool, ShenandoahImplicitGCInvokesConcurrent, false, EXPERIMENTAL, \ "Should internally-caused GC requests invoke concurrent cycles, " \ "should they do the stop-the-world (Degenerated / Full GC)? " \ "Many heuristics automatically enable this. This option is " \ "similar to global ExplicitGCInvokesConcurrent.") \ \ - diagnostic(bool, ShenandoahHumongousMoves, true, \ + product(bool, ShenandoahHumongousMoves, true, DIAGNOSTIC, \ "Allow moving humongous regions. This makes GC more resistant " \ "to external fragmentation that may otherwise fail other " \ "humongous allocations, at the expense of higher GC copying " \ "costs. Currently affects stop-the-world (Full) cycle only.") \ \ - diagnostic(bool, ShenandoahOOMDuringEvacALot, false, \ + product(bool, ShenandoahOOMDuringEvacALot, false, DIAGNOSTIC, \ "Testing: simulate OOM during evacuation.") \ \ - diagnostic(bool, ShenandoahAllocFailureALot, false, \ + product(bool, ShenandoahAllocFailureALot, false, DIAGNOSTIC, \ "Testing: make lots of artificial allocation failures.") \ \ - experimental(intx, ShenandoahMarkScanPrefetch, 32, \ + product(intx, ShenandoahMarkScanPrefetch, 32, EXPERIMENTAL, \ "How many objects to prefetch ahead when traversing mark bitmaps."\ "Set to 0 to disable prefetching.") \ range(0, 256) \ \ - experimental(uintx, ShenandoahMarkLoopStride, 1000, \ + product(uintx, ShenandoahMarkLoopStride, 1000, EXPERIMENTAL, \ "How many items to process during one marking iteration before " \ "checking for cancellation, yielding, etc. Larger values improve "\ "marking performance at expense of responsiveness.") \ \ - experimental(uintx, ShenandoahParallelRegionStride, 1024, \ + product(uintx, ShenandoahParallelRegionStride, 1024, EXPERIMENTAL, \ "How many regions to process at once during parallel region " \ "iteration. Affects heaps with lots of regions.") \ \ - experimental(size_t, ShenandoahSATBBufferSize, 1 * K, \ + product(size_t, ShenandoahSATBBufferSize, 1 * K, EXPERIMENTAL, \ "Number of entries in an SATB log buffer.") \ range(1, max_uintx) \ \ - experimental(uintx, ShenandoahSATBBufferFlushInterval, 100, \ + product(uintx, ShenandoahSATBBufferFlushInterval, 100, EXPERIMENTAL, \ "Forcefully flush non-empty SATB buffers at this interval. " \ "Time is in milliseconds.") \ \ - diagnostic(bool, ShenandoahPreclean, true, \ + product(bool, ShenandoahPreclean, true, DIAGNOSTIC, \ "Do concurrent preclean phase before final mark: process " \ "definitely alive references to avoid dealing with them during " \ "pause.") \ \ - experimental(bool, ShenandoahSuspendibleWorkers, false, \ + product(bool, ShenandoahSuspendibleWorkers, false, EXPERIMENTAL, \ "Suspend concurrent GC worker threads at safepoints") \ \ - diagnostic(bool, ShenandoahSATBBarrier, true, \ + product(bool, ShenandoahSATBBarrier, true, DIAGNOSTIC, \ "Turn on/off SATB barriers in Shenandoah") \ \ - diagnostic(bool, ShenandoahStoreValEnqueueBarrier, false, \ + product(bool, ShenandoahStoreValEnqueueBarrier, false, DIAGNOSTIC, \ "Turn on/off enqueuing of oops for storeval barriers") \ \ - diagnostic(bool, ShenandoahCASBarrier, true, \ + product(bool, ShenandoahCASBarrier, true, DIAGNOSTIC, \ "Turn on/off CAS barriers in Shenandoah") \ \ - diagnostic(bool, ShenandoahCloneBarrier, true, \ + product(bool, ShenandoahCloneBarrier, true, DIAGNOSTIC, \ "Turn on/off clone barriers in Shenandoah") \ \ - diagnostic(bool, ShenandoahLoadRefBarrier, true, \ + product(bool, ShenandoahLoadRefBarrier, true, DIAGNOSTIC, \ "Turn on/off load-reference barriers in Shenandoah") \ \ - diagnostic(uintx, ShenandoahCodeRootsStyle, 2, \ + product(uintx, ShenandoahCodeRootsStyle, 2, DIAGNOSTIC, \ "Use this style to scan the code cache roots:" \ " 0 - sequential iterator;" \ " 1 - parallel iterator;" \ @@ -351,12 +345,13 @@ develop(bool, ShenandoahVerifyOptoBarriers, false, \ "Verify no missing barriers in C2.") \ \ - diagnostic(bool, ShenandoahLoopOptsAfterExpansion, true, \ + product(bool, ShenandoahLoopOptsAfterExpansion, true, DIAGNOSTIC, \ "Attempt more loop opts after barrier expansion.") \ \ - diagnostic(bool, ShenandoahSelfFixing, true, \ + product(bool, ShenandoahSelfFixing, true, DIAGNOSTIC, \ "Fix references with load reference barrier. Disabling this " \ - "might degrade performance.") \ + "might degrade performance.") +// end of GC_SHENANDOAH_FLAGS #endif // SHARE_GC_SHENANDOAH_SHENANDOAH_GLOBALS_HPP diff --git a/src/hotspot/share/gc/z/zForwardingEntry.hpp b/src/hotspot/share/gc/z/zForwardingEntry.hpp index a6db411c314..2aa538f0ec2 100644 --- a/src/hotspot/share/gc/z/zForwardingEntry.hpp +++ b/src/hotspot/share/gc/z/zForwardingEntry.hpp @@ -27,6 +27,7 @@ #include "gc/z/zBitField.hpp" #include "memory/allocation.hpp" #include "metaprogramming/primitiveConversions.hpp" +#include <type_traits> // // Forwarding entry layout @@ -46,7 +47,7 @@ // class ZForwardingEntry { - friend class PrimitiveConversions; + friend struct PrimitiveConversions::Translate<ZForwardingEntry>; private: typedef ZBitField<uint64_t, bool, 0, 1> field_populated; @@ -79,7 +80,7 @@ class ZForwardingEntry { // Needed to allow atomic operations on ZForwardingEntry template <> -struct PrimitiveConversions::Translate<ZForwardingEntry> : public TrueType { +struct PrimitiveConversions::Translate<ZForwardingEntry> : public std::true_type { typedef ZForwardingEntry Value; typedef uint64_t Decayed; diff --git a/src/hotspot/share/gc/z/zFuture.inline.hpp b/src/hotspot/share/gc/z/zFuture.inline.hpp index 26d58b69d49..1919438d06d 100644 --- a/src/hotspot/share/gc/z/zFuture.inline.hpp +++ b/src/hotspot/share/gc/z/zFuture.inline.hpp @@ -46,7 +46,7 @@ inline T ZFuture<T>::get() { // Wait for notification Thread* const thread = Thread::current(); if (thread->is_Java_thread()) { - _sema.wait_with_safepoint_check((JavaThread*)thread); + _sema.wait_with_safepoint_check(thread->as_Java_thread()); } else { _sema.wait(); } diff --git a/src/hotspot/share/gc/z/zGlobals.hpp b/src/hotspot/share/gc/z/zGlobals.hpp index 138b9486f03..690227e3a8d 100644 --- a/src/hotspot/share/gc/z/zGlobals.hpp +++ b/src/hotspot/share/gc/z/zGlobals.hpp @@ -149,6 +149,6 @@ const size_t ZMarkProactiveFlushMax = 10; const size_t ZMarkTerminateFlushMax = 3; // Try complete mark timeout -const uint64_t ZMarkCompleteTimeout = 1; // ms +const uint64_t ZMarkCompleteTimeout = 1000; // us #endif // SHARE_GC_Z_ZGLOBALS_HPP diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index 8ea20b97fa4..ed409b58e87 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -563,9 +563,9 @@ class ZMarkTimeout : public StackObj { bool _expired; public: - ZMarkTimeout(uint64_t timeout_in_millis) : + ZMarkTimeout(uint64_t timeout_in_micros) : _start(Ticks::now()), - _timeout(_start.value() + TimeHelper::millis_to_counter(timeout_in_millis)), + _timeout(_start.value() + TimeHelper::micros_to_counter(timeout_in_micros)), _check_interval(200), _check_at(_check_interval), _check_count(0), @@ -591,9 +591,9 @@ class ZMarkTimeout : public StackObj { } }; -void ZMark::work_with_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, uint64_t timeout_in_millis) { +void ZMark::work_with_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, uint64_t timeout_in_micros) { ZStatTimer timer(ZSubPhaseMarkTryComplete); - ZMarkTimeout timeout(timeout_in_millis); + ZMarkTimeout timeout(timeout_in_micros); for (;;) { if (!drain_and_flush(stripe, stacks, cache, &timeout)) { @@ -611,15 +611,15 @@ void ZMark::work_with_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThrea } } -void ZMark::work(uint64_t timeout_in_millis) { +void ZMark::work(uint64_t timeout_in_micros) { ZMarkCache cache(_stripes.nstripes()); ZMarkStripe* const stripe = _stripes.stripe_for_worker(_nworkers, ZThread::worker_id()); ZMarkThreadLocalStacks* const stacks = ZThreadLocalData::stacks(Thread::current()); - if (timeout_in_millis == 0) { + if (timeout_in_micros == 0) { work_without_timeout(&cache, stripe, stacks); } else { - work_with_timeout(&cache, stripe, stacks, timeout_in_millis); + work_with_timeout(&cache, stripe, stacks, timeout_in_micros); } // Make sure stacks have been flushed @@ -668,13 +668,13 @@ class ZMarkConcurrentRootsTask : public ZTask { class ZMarkTask : public ZTask { private: ZMark* const _mark; - const uint64_t _timeout_in_millis; + const uint64_t _timeout_in_micros; public: - ZMarkTask(ZMark* mark, uint64_t timeout_in_millis = 0) : + ZMarkTask(ZMark* mark, uint64_t timeout_in_micros = 0) : ZTask("ZMarkTask"), _mark(mark), - _timeout_in_millis(timeout_in_millis) { + _timeout_in_micros(timeout_in_micros) { _mark->prepare_work(); } @@ -683,7 +683,7 @@ class ZMarkTask : public ZTask { } virtual void work() { - _mark->work(_timeout_in_millis); + _mark->work(_timeout_in_micros); } }; diff --git a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp index 9250623740f..32c16fd959e 100644 --- a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp +++ b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ oop ZObjArrayAllocator::finish(HeapWord* mem) const { if (remaining > 0) { // Safepoint - ThreadBlockInVM tbivm((JavaThread*)_thread); + ThreadBlockInVM tbivm(_thread->as_Java_thread()); } } diff --git a/src/hotspot/share/gc/z/z_globals.hpp b/src/hotspot/share/gc/z/z_globals.hpp index b89a3c0ef13..5d921def086 100644 --- a/src/hotspot/share/gc/z/z_globals.hpp +++ b/src/hotspot/share/gc/z/z_globals.hpp @@ -28,13 +28,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ @@ -61,23 +55,25 @@ "Uncommit memory if it has been unused for the specified " \ "amount of time (in seconds)") \ \ - diagnostic(uint, ZStatisticsInterval, 10, \ + product(uint, ZStatisticsInterval, 10, DIAGNOSTIC, \ "Time between statistics print outs (in seconds)") \ range(1, (uint)-1) \ \ - diagnostic(bool, ZVerifyViews, false, \ + product(bool, ZVerifyViews, false, DIAGNOSTIC, \ "Verify heap view accesses") \ \ - diagnostic(bool, ZVerifyRoots, trueInDebug, \ + product(bool, ZVerifyRoots, trueInDebug, DIAGNOSTIC, \ "Verify roots") \ \ - diagnostic(bool, ZVerifyObjects, false, \ + product(bool, ZVerifyObjects, false, DIAGNOSTIC, \ "Verify objects") \ \ - diagnostic(bool, ZVerifyMarking, trueInDebug, \ + product(bool, ZVerifyMarking, trueInDebug, DIAGNOSTIC, \ "Verify marking stacks") \ \ - diagnostic(bool, ZVerifyForwarding, false, \ + product(bool, ZVerifyForwarding, false, DIAGNOSTIC, \ "Verify forwarding tables") +// end of GC_Z_FLAGS + #endif // SHARE_GC_Z_Z_GLOBALS_HPP diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index a4b97139e58..15b064dcb7d 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -490,6 +490,14 @@ JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package); JNIEXPORT void JNICALL JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module); +/* + * Define all modules that have been stored in the CDS archived heap. + * platform_loader: the built-in platform class loader + * system_loader: the built-in system class loader + */ +JNIEXPORT void JNICALL +JVM_DefineArchivedModules(JNIEnv *env, jobject platform_loader, jobject system_loader); + /* * Reflection support functions */ diff --git a/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp b/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp index 100d9deb371..4dc9fba7ae5 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp @@ -68,12 +68,6 @@ static bool update_class_file_load_hook_event(jvmtiEventMode mode) { return set_event_notification_mode(mode, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL); } -static JavaThread* current_java_thread() { - Thread* this_thread = Thread::current(); - assert(this_thread != NULL && this_thread->is_Java_thread(), "invariant"); - return static_cast<JavaThread*>(this_thread); -} - // jvmti event callbacks require C linkage extern "C" void JNICALL jfr_on_class_file_load_hook(jvmtiEnv *jvmti_env, JNIEnv* jni_env, @@ -104,7 +98,7 @@ extern "C" void JNICALL jfr_on_class_file_load_hook(jvmtiEnv *jvmti_env, static jclass* create_classes_array(jint classes_count, TRAPS) { assert(classes_count > 0, "invariant"); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD)); - ThreadInVMfromNative tvmfn((JavaThread*)THREAD); + ThreadInVMfromNative tvmfn(THREAD->as_Java_thread()); jclass* const classes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jclass, classes_count); if (NULL == classes) { char error_buffer[ERROR_MSG_BUFFER_SIZE]; @@ -121,7 +115,7 @@ static jclass* create_classes_array(jint classes_count, TRAPS) { static void log_and_throw(jvmtiError error, TRAPS) { if (!HAS_PENDING_EXCEPTION) { DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD)); - ThreadInVMfromNative tvmfn((JavaThread*)THREAD); + ThreadInVMfromNative tvmfn(THREAD->as_Java_thread()); const char base_error_msg[] = "JfrJvmtiAgent::retransformClasses failed: "; size_t length = sizeof base_error_msg; // includes terminating null const char* const jvmti_error_name = JvmtiUtil::error_name(error); @@ -142,7 +136,7 @@ static void check_exception_and_log(JNIEnv* env, TRAPS) { if (env->ExceptionOccurred()) { // array index out of bound DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD)); - ThreadInVMfromNative tvmfn((JavaThread*)THREAD); + ThreadInVMfromNative tvmfn(THREAD->as_Java_thread()); log_error(jfr, system)("GetObjectArrayElement threw an exception"); return; } @@ -171,7 +165,7 @@ void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, } { // inspecting the oop/klass requires a thread transition - ThreadInVMfromNative transition((JavaThread*)THREAD); + ThreadInVMfromNative transition(THREAD->as_Java_thread()); for (jint i = 0; i < classes_count; ++i) { jclass clz = classes[i]; if (!JdkJfrEvent::is_a(clz)) { @@ -233,7 +227,7 @@ static bool unregister_callbacks(JavaThread* jt) { JfrJvmtiAgent::JfrJvmtiAgent() {} JfrJvmtiAgent::~JfrJvmtiAgent() { - JavaThread* jt = current_java_thread(); + JavaThread* jt = JavaThread::current(); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); if (jfr_jvmti_env != NULL) { ThreadToNativeFromVM transition(jt); @@ -273,7 +267,7 @@ static void log_and_throw_illegal_state_exception(TRAPS) { bool JfrJvmtiAgent::create() { assert(agent == NULL, "invariant"); - JavaThread* const jt = current_java_thread(); + JavaThread* const jt = JavaThread::current(); if (!is_valid_jvmti_phase()) { log_and_throw_illegal_state_exception(jt); return false; diff --git a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp index 423f0a0be1b..c7c38378b1f 100644 --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp @@ -51,20 +51,17 @@ #ifdef ASSERT void JfrJavaSupport::check_java_thread_in_vm(Thread* t) { assert(t != NULL, "invariant"); - assert(t->is_Java_thread(), "invariant"); - assert(((JavaThread*)t)->thread_state() == _thread_in_vm, "invariant"); + assert(t->as_Java_thread()->thread_state() == _thread_in_vm, "invariant"); } void JfrJavaSupport::check_java_thread_in_native(Thread* t) { assert(t != NULL, "invariant"); - assert(t->is_Java_thread(), "invariant"); - assert(((JavaThread*)t)->thread_state() == _thread_in_native, "invariant"); + assert(t->as_Java_thread()->thread_state() == _thread_in_native, "invariant"); } static void check_new_unstarted_java_thread(Thread* t) { assert(t != NULL, "invariant"); - assert(t->is_Java_thread(), "invariant"); - assert(((JavaThread*)t)->thread_state() == _thread_new, "invariant"); + assert(t->as_Java_thread()->thread_state() == _thread_new, "invariant"); } #endif @@ -836,7 +833,7 @@ void JfrJavaSupport::on_thread_start(Thread* t) { } DEBUG_ONLY(check_new_unstarted_java_thread(t);) HandleMark hm(t); - if (check_exclusion_state_on_thread_start((JavaThread*)t)) { + if (check_exclusion_state_on_thread_start(t->as_Java_thread())) { JfrThreadLocal::exclude(t); } } diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp index 0faf97ac7cf..479fca01324 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp @@ -261,10 +261,10 @@ static void install_stack_traces(const ObjectSampler* sampler, JfrStackTraceRepo void ObjectSampleCheckpoint::on_rotation(const ObjectSampler* sampler, JfrStackTraceRepository& stack_trace_repo) { assert(sampler != NULL, "invariant"); assert(LeakProfiler::is_running(), "invariant"); - Thread* const thread = Thread::current(); + JavaThread* const thread = JavaThread::current(); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(thread);) // can safepoint here - ThreadInVMfromNative transition((JavaThread*)thread); + ThreadInVMfromNative transition(thread); MutexLocker lock(ClassLoaderDataGraph_lock); // the lock is needed to ensure the unload lists do not grow in the middle of inspection. install_stack_traces(sampler, stack_trace_repo); diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index d8d72a916da..5295b137ccf 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -179,7 +179,7 @@ TRACE_REQUEST_FUNC(CPULoad) { { // Can take some time on certain platforms, especially under heavy load. // Transition to native to avoid unnecessary stalls for pending safepoint synchronizations. - ThreadToNativeFromVM transition((JavaThread*)Thread::current()); + ThreadToNativeFromVM transition(JavaThread::current()); ret_val = JfrOSInterface::cpu_loads_process(&u, &s, &t); } if (ret_val == OS_ERR) { @@ -259,7 +259,7 @@ TRACE_REQUEST_FUNC(ThreadContextSwitchRate) { { // Can take some time on certain platforms, especially under heavy load. // Transition to native to avoid unnecessary stalls for pending safepoint synchronizations. - ThreadToNativeFromVM transition((JavaThread*)Thread::current()); + ThreadToNativeFromVM transition(JavaThread::current()); ret_val = JfrOSInterface::context_switch_rate(&rate); } if (ret_val == OS_ERR) { @@ -643,4 +643,3 @@ TRACE_REQUEST_FUNC(ShenandoahHeapRegionInformation) { } #endif } - diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp index 602b10859a4..3d66f12e87d 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp @@ -174,7 +174,7 @@ void OSThreadSampler::do_task(const os::SuspendedThreadTaskContext& context) { * using a signal handler / __try block. Don't take locks, rely on destructors or * leave memory (in case of signal / exception) in an inconsistent state. */ void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) { - JavaThread* jth = (JavaThread*)context.thread(); + JavaThread* jth = context.thread()->as_Java_thread(); // Skip sample if we signaled a thread that moved to other state if (!thread_state_in_java(jth)) { return; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index 3ba27e40386..a66241b1fcf 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -387,7 +387,7 @@ size_t JfrCheckpointManager::write_static_type_set(Thread* thread) { size_t JfrCheckpointManager::write_threads(Thread* thread) { assert(thread != NULL, "invariant"); // can safepoint here - ThreadInVMfromNative transition((JavaThread*)thread); + ThreadInVMfromNative transition(thread->as_Java_thread()); ResetNoHandleMark rnhm; ResourceMark rm(thread); HandleMark hm(thread); @@ -412,10 +412,10 @@ void JfrCheckpointManager::on_rotation() { void JfrCheckpointManager::clear_type_set() { assert(!JfrRecorder::is_recording(), "invariant"); - Thread* t = Thread::current(); + JavaThread* t = JavaThread::current(); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(t)); // can safepoint here - ThreadInVMfromNative transition((JavaThread*)t); + ThreadInVMfromNative transition(t); ResetNoHandleMark rnhm; MutexLocker cld_lock(ClassLoaderDataGraph_lock); MutexLocker module_lock(Module_lock); @@ -424,10 +424,10 @@ void JfrCheckpointManager::clear_type_set() { void JfrCheckpointManager::write_type_set() { { - Thread* const thread = Thread::current(); + JavaThread* const thread = JavaThread::current(); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(thread)); // can safepoint here - ThreadInVMfromNative transition((JavaThread*)thread); + ThreadInVMfromNative transition(thread); ResetNoHandleMark rnhm; MutexLocker cld_lock(thread, ClassLoaderDataGraph_lock); MutexLocker module_lock(thread, Module_lock); @@ -467,7 +467,7 @@ size_t JfrCheckpointManager::flush_type_set() { Thread* const thread = Thread::current(); if (thread->is_Java_thread()) { // can safepoint here - ThreadInVMfromNative transition((JavaThread*)thread); + ThreadInVMfromNative transition(thread->as_Java_thread()); ResetNoHandleMark rnhm; elements = ::flush_type_set(thread); } else { @@ -496,9 +496,8 @@ class JfrNotifyClosure : public ThreadClosure { public: void do_thread(Thread* thread) { assert(thread != NULL, "invariant"); - assert(thread->is_Java_thread(), "invariant"); assert_locked_or_safepoint(Threads_lock); - JfrJavaEventWriter::notify((JavaThread*)thread); + JfrJavaEventWriter::notify(thread->as_Java_thread()); } }; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.cpp index 704e7fd6012..57407699e55 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.cpp @@ -56,7 +56,7 @@ void JfrMetadataEvent::write(JfrChunkWriter& chunkwriter) { if (last_metadata_id == metadata_id && chunkwriter.has_metadata()) { return; } - JavaThread* const jt = (JavaThread*)Thread::current(); + JavaThread* const jt = JavaThread::current(); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt)); // can safepoint here ThreadInVMfromNative transition(jt); @@ -76,8 +76,7 @@ void JfrMetadataEvent::write(JfrChunkWriter& chunkwriter) { } void JfrMetadataEvent::update(jbyteArray metadata) { - JavaThread* thread = (JavaThread*)Thread::current(); - assert(thread->is_Java_thread(), "invariant"); + JavaThread* thread = JavaThread::current(); DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread)); if (metadata_blob != NULL) { JfrJavaSupport::destroy_global_jni_handle(metadata_blob); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.cpp index cff49b23c5b..8e747142f80 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,8 +89,7 @@ traceid JfrThreadId::id(const Thread* t) { if (!t->is_Java_thread()) { return os_id(t); } - const JavaThread* const jt = (JavaThread*)t; - const oop thread_obj = jt->threadObj(); + const oop thread_obj = t->as_Java_thread()->threadObj(); return thread_obj != NULL ? java_lang_Thread::thread_id(thread_obj) : 0; } @@ -108,8 +107,7 @@ traceid JfrThreadId::jfr_id(const Thread* t) { // caller needs ResourceMark const char* get_java_thread_name(const Thread* t) { assert(t != NULL, "invariant"); - assert(t->is_Java_thread(), "invariant"); - const JavaThread* const jt = ((JavaThread*)t); + const JavaThread* const jt = t->as_Java_thread(); const char* name_str = "<no-name - thread name unresolved>"; const oop thread_obj = jt->threadObj(); if (thread_obj != NULL) { diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp index 047ac8f5f7a..840d79d24ef 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp @@ -98,7 +98,7 @@ void JfrCheckpointThreadClosure::do_thread(Thread* t) { if (t->is_Java_thread()) { _writer.write(name); _writer.write(JfrThreadId::id(t)); - _writer.write(JfrThreadGroup::thread_group_id((JavaThread*)t, _curthread)); + _writer.write(JfrThreadGroup::thread_group_id(t->as_Java_thread(), _curthread)); return; } _writer.write((const char*)NULL); // java name @@ -274,7 +274,7 @@ void JfrThreadConstant::serialize(JfrCheckpointWriter& writer) { if (_thread->is_Java_thread()) { writer.write(name); writer.write(JfrThreadId::id(_thread)); - JavaThread* const jt = (JavaThread*)_thread; + JavaThread* const jt = _thread->as_Java_thread(); const traceid thread_group_id = JfrThreadGroup::thread_group_id(jt, jt); writer.write(thread_group_id); JfrThreadGroup::serialize(&writer, thread_group_id); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp index 138a85ed005..6b2c91a9442 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp @@ -154,7 +154,7 @@ traceid JfrTraceId::assign_thread_id() { traceid JfrTraceId::load_raw(jclass jc) { assert(jc != NULL, "invariant"); - assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_vm, "invariant"); + assert(JavaThread::current()->thread_state() == _thread_in_vm, "invariant"); const oop my_oop = JNIHandles::resolve(jc); assert(my_oop != NULL, "invariant"); return load_raw(java_lang_Class::as_Klass(my_oop)); @@ -190,7 +190,7 @@ void JfrTraceId::restore(const Klass* k) { bool JfrTraceId::in_visible_set(const jclass jc) { assert(jc != NULL, "invariant"); - assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_vm, "invariant"); + assert(JavaThread::current()->thread_state() == _thread_in_vm, "invariant"); const oop mirror = JNIHandles::resolve(jc); assert(mirror != NULL, "invariant"); return in_visible_set(java_lang_Class::as_Klass(mirror)); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp index e7225fdf2f0..ffd56852b49 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp @@ -100,7 +100,7 @@ inline traceid JfrTraceId::load_raw(const ClassLoaderData* cld) { inline bool JfrTraceId::in_visible_set(const Klass* klass) { assert(klass != NULL, "invariant"); - assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_vm, "invariant"); + assert(JavaThread::current()->thread_state() == _thread_in_vm, "invariant"); return (IS_JDK_JFR_EVENT_SUBKLASS(klass) && !klass->is_abstract()) || IS_EVENT_HOST_KLASS(klass); } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp index 8dd5fef8e55..863429a1313 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp @@ -73,7 +73,7 @@ void JfrTraceIdLoadBarrier::do_klasses(klass_callback callback, bool previous_ep traceid JfrTraceIdLoadBarrier::load(jclass jc) { assert(jc != NULL, "invariant"); - assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_vm, "invariant"); + assert(JavaThread::current()->thread_state() == _thread_in_vm, "invariant"); const oop my_oop = JNIHandles::resolve(jc); assert(my_oop != NULL, "invariant"); return load(java_lang_Class::as_Klass(my_oop)); diff --git a/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp index 4a71437e7e1..90ec9b356ab 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp @@ -53,9 +53,9 @@ static jobject get_chunk_monitor(Thread* thread) { } static void notify() { - Thread* const thread = Thread::current(); + JavaThread* const thread = JavaThread::current(); // can safepoint here - ThreadInVMfromNative transition((JavaThread*)thread); + ThreadInVMfromNative transition(thread); ResetNoHandleMark rnhm; JfrJavaSupport::notify_all(get_chunk_monitor(thread), thread); } diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp index a77a5405761..dd2ffefff8b 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp @@ -504,7 +504,7 @@ class JavaThreadInVMAndNative : public StackObj { JavaThreadState _original_state; public: - JavaThreadInVMAndNative(Thread* t) : _jt(t->is_Java_thread() ? (JavaThread*)t : NULL), + JavaThreadInVMAndNative(Thread* t) : _jt(t->is_Java_thread() ? t->as_Java_thread() : NULL), _original_state(_thread_max_state) { if (_jt != NULL) { _original_state = _jt->thread_state(); diff --git a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp index 8477a805a6d..bfade7236b7 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ JfrPostBox::JfrPostBox() : static bool is_thread_lock_aversive() { Thread* const thread = Thread::current(); - return (thread->is_Java_thread() && ((JavaThread*)thread)->thread_state() != _thread_in_vm) || thread->is_VM_thread(); + return (thread->is_Java_thread() && thread->as_Java_thread()->thread_state() != _thread_in_vm) || thread->is_VM_thread(); } static bool is_synchronous(int messages) { diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index 5d1f0eeeff2..dc6c812e3ae 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -450,7 +450,7 @@ void JfrRecorderService::pre_safepoint_clear() { void JfrRecorderService::invoke_safepoint_clear() { JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_clear> safepoint_task(*this); - ThreadInVMfromNative transition((JavaThread*)Thread::current()); + ThreadInVMfromNative transition(JavaThread::current()); VMThread::execute(&safepoint_task); } @@ -561,7 +561,7 @@ void JfrRecorderService::pre_safepoint_write() { void JfrRecorderService::invoke_safepoint_write() { JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this); // can safepoint here - ThreadInVMfromNative transition((JavaThread*)Thread::current()); + ThreadInVMfromNative transition(JavaThread::current()); VMThread::execute(&safepoint_task); } diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp index 82e84542d9e..d62ad184cdd 100644 --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,7 +142,7 @@ traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) { } assert(frames != NULL, "invariant"); assert(tl->stackframes() == frames, "invariant"); - return instance().record_for((JavaThread*)thread, skip, frames, tl->stackdepth()); + return instance().record_for(thread->as_Java_thread(), skip, frames, tl->stackdepth()); } traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames) { diff --git a/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp b/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp index d23ca077564..4c852faaa86 100644 --- a/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp +++ b/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * 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,9 +30,8 @@ JfrAllocationTracer::JfrAllocationTracer(HeapWord* obj, size_t alloc_size, Thread* thread) : _tl(NULL) { if (LeakProfiler::is_running()) { - assert(thread->is_Java_thread(), "invariant"); _tl = thread->jfr_thread_local(); - LeakProfiler::sample(obj, alloc_size, (JavaThread*)thread); + LeakProfiler::sample(obj, alloc_size, thread->as_Java_thread()); } } diff --git a/src/hotspot/share/jfr/support/jfrEpochSynchronization.cpp b/src/hotspot/share/jfr/support/jfrEpochSynchronization.cpp index c14b766332d..bc013e56ad6 100644 --- a/src/hotspot/share/jfr/support/jfrEpochSynchronization.cpp +++ b/src/hotspot/share/jfr/support/jfrEpochSynchronization.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,10 +31,7 @@ JfrEpochSynchronization::JfrEpochSynchronization() { if (JfrTraceIdEpoch::is_synchronizing()) { // only at a safepoint - Thread* thread = Thread::current(); - assert(thread != NULL, "invariant"); - assert(thread->is_Java_thread(), "invariant"); - JavaThread* const jt = (JavaThread*)thread; + JavaThread* const jt = JavaThread::current(); assert(jt->thread_state() == _thread_in_native, "invariant"); // use ordinary transition to have the thread block and await the new epoch ThreadInVMfromNative transition(jt); diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 60077418bba..48b6d657ebc 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -95,7 +95,7 @@ void JfrThreadLocal::on_start(Thread* t) { JfrCheckpointManager::write_thread_checkpoint(t); if (!t->jfr_thread_local()->is_excluded()) { if (t->is_Java_thread()) { - send_java_thread_start_event((JavaThread*)t); + send_java_thread_start_event(t->as_Java_thread()); } } } @@ -160,7 +160,7 @@ void JfrThreadLocal::on_exit(Thread* t) { assert(!tl->is_dead(), "invariant"); if (JfrRecorder::is_recording()) { if (t->is_Java_thread()) { - JavaThread* const jt = (JavaThread*)t; + JavaThread* const jt = t->as_Java_thread(); ObjectSampleCheckpoint::on_thread_exit(jt); send_java_thread_end_events(tl->thread_id(), jt); } diff --git a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp index d4dcdeb58d2..a69e4bed216 100644 --- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp +++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp @@ -171,7 +171,7 @@ class JfrJavaEventWriterNotificationClosure : public ThreadClosure { public: void do_thread(Thread* t) { if (t->is_Java_thread()) { - JfrJavaEventWriter::notify((JavaThread*)t); + JfrJavaEventWriter::notify(t->as_Java_thread()); } } }; diff --git a/src/hotspot/share/jvmci/jvmci.cpp b/src/hotspot/share/jvmci/jvmci.cpp index e3ad542543c..ab0cde9f922 100644 --- a/src/hotspot/share/jvmci/jvmci.cpp +++ b/src/hotspot/share/jvmci/jvmci.cpp @@ -23,9 +23,11 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" +#include "compiler/compileTask.hpp" #include "gc/shared/collectedHeap.hpp" #include "jvmci/jvmci.hpp" #include "jvmci/jvmciJavaClasses.hpp" +#include "jvmci/jvmciEnv.hpp" #include "jvmci/jvmciRuntime.hpp" #include "jvmci/metadataHandles.hpp" #include "memory/resourceArea.hpp" @@ -123,6 +125,18 @@ void JVMCI::initialize_globals() { } } +JavaThread* JVMCI::compilation_tick(JavaThread* thread) { + if (thread->is_Compiler_thread()) { + CompileTask *task = thread->as_CompilerThread()->task(); + if (task != NULL) { + JVMCICompileState *state = task->blocking_jvmci_compile_state(); + if (state != NULL) { + state->inc_compilation_ticks(); + } + } + } + return thread; +} void JVMCI::metadata_do(void f(Metadata*)) { if (_java_runtime != NULL) { diff --git a/src/hotspot/share/jvmci/jvmci.hpp b/src/hotspot/share/jvmci/jvmci.hpp index f5df7f13532..e1b0cc0bf5b 100644 --- a/src/hotspot/share/jvmci/jvmci.hpp +++ b/src/hotspot/share/jvmci/jvmci.hpp @@ -110,6 +110,11 @@ class JVMCI : public AllStatic { static void initialize_compiler(TRAPS); + // Increments a value indicating some JVMCI compilation activity + // happened on `thread` if it is a CompilerThread. + // Returns `thread`. + static JavaThread* compilation_tick(JavaThread* thread); + static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; } // Gets the single runtime for JVMCI on the Java heap. This is the only // JVMCI runtime available when !UseJVMCINativeLibrary. diff --git a/src/hotspot/share/jvmci/jvmciCompiler.cpp b/src/hotspot/share/jvmci/jvmciCompiler.cpp index 804c38fe85a..bda41203993 100644 --- a/src/hotspot/share/jvmci/jvmciCompiler.cpp +++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp @@ -37,6 +37,7 @@ JVMCICompiler::JVMCICompiler() : AbstractCompiler(compiler_jvmci) { _bootstrapping = false; _bootstrap_compilation_request_handled = false; _methods_compiled = 0; + _global_compilation_ticks = 0; assert(_instance == NULL, "only one instance allowed"); _instance = this; } @@ -83,7 +84,7 @@ void JVMCICompiler::bootstrap(TRAPS) { do { // Loop until there is something in the queue. do { - ((JavaThread*)THREAD)->sleep(100); + THREAD->as_Java_thread()->sleep(100); qsize = CompileBroker::queue_size(CompLevel_full_optimization); } while (!_bootstrap_compilation_request_handled && first_round && qsize == 0); first_round = false; @@ -154,3 +155,12 @@ void JVMCICompiler::print_compilation_timers() { tty->print_cr(" JVMCI code install time: %6.3f s", code_install_time); } } + +void JVMCICompiler::inc_methods_compiled() { + Atomic::inc(&_methods_compiled); + Atomic::inc(&_global_compilation_ticks); +} + +void JVMCICompiler::inc_global_compilation_ticks() { + Atomic::inc(&_global_compilation_ticks); +} \ No newline at end of file diff --git a/src/hotspot/share/jvmci/jvmciCompiler.hpp b/src/hotspot/share/jvmci/jvmciCompiler.hpp index b522a54f525..db032b3c8ac 100644 --- a/src/hotspot/share/jvmci/jvmciCompiler.hpp +++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp @@ -42,6 +42,10 @@ class JVMCICompiler : public AbstractCompiler { */ volatile int _methods_compiled; + // Incremented periodically by JVMCI compiler threads + // to indicate JVMCI compilation activity. + volatile int _global_compilation_ticks; + static JVMCICompiler* _instance; static elapsedTimer _codeInstallTimer; @@ -99,15 +103,16 @@ class JVMCICompiler : public AbstractCompiler { // Print compilation timers and statistics virtual void print_timers(); - /** - * Gets the number of methods that have been successfully compiled by - * a call to JVMCICompiler::compile_method(). - */ + // Gets the number of methods that have been successfully compiled by + // a call to JVMCICompiler::compile_method(). int methods_compiled() { return _methods_compiled; } + void inc_methods_compiled(); - void inc_methods_compiled() { - Atomic::inc(&_methods_compiled); - } + // Gets a value indicating JVMCI compilation activity on any thread. + // If successive calls to this method return a different value, then + // some degree of JVMCI compilation occurred between the calls. + int global_compilation_ticks() const { return _global_compilation_ticks; } + void inc_global_compilation_ticks(); // Print compilation timers and statistics static void print_compilation_timers(); diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index df006cd6487..b0443078a0b 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -48,6 +48,7 @@ #include "runtime/deoptimization.hpp" #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/reflectionUtils.hpp" @@ -132,7 +133,7 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) { TRACE_CALL(result_type, jvmci_ ## name signature) \ JVMCI_VM_ENTRY_MARK; \ ResourceMark rm; \ - JNI_JVMCIENV(thread, env); + JNI_JVMCIENV(JVMCI::compilation_tick(thread), env); static JavaThread* get_current_thread(bool allow_null=true) { Thread* thread = Thread::current_or_null_safe(); @@ -140,8 +141,7 @@ static JavaThread* get_current_thread(bool allow_null=true) { assert(allow_null, "npe"); return NULL; } - assert(thread->is_Java_thread(), "must be"); - return (JavaThread*) thread; + return thread->as_Java_thread(); } // Entry to native method implementation that transitions @@ -2640,19 +2640,11 @@ C2V_VMENTRY_0(jlong, ticksNow, (JNIEnv* env, jobject)) return CompilerEvent::ticksNow(); } -C2V_VMENTRY_0(jint, registerCompilerPhases, (JNIEnv* env, jobject, jobjectArray jphases)) +C2V_VMENTRY_0(jint, registerCompilerPhase, (JNIEnv* env, jobject, jstring jphase_name)) #if INCLUDE_JFR - if (jphases == NULL) { - return -1; - } - JVMCIObjectArray phases = JVMCIENV->wrap(jphases); - int len = JVMCIENV->get_length(phases); - GrowableArray<const char*>* jvmci_phase_names = new GrowableArray<const char*>(len); - for (int i = 0; i < len; i++) { - JVMCIObject phase = JVMCIENV->get_object_at(phases, i); - jvmci_phase_names->append(strdup(JVMCIENV->as_utf8_string(phase))); - } - return CompilerEvent::PhaseEvent::register_phases(jvmci_phase_names); + JVMCIObject phase_name = JVMCIENV->wrap(jphase_name); + const char *name = JVMCIENV->as_utf8_string(phase_name); + return CompilerEvent::PhaseEvent::get_phase_id(name, true, true, true); #else return -1; #endif // !INCLUDE_JFR @@ -2824,7 +2816,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)}, {CC "callSystemExit", CC "(I)V", FN_PTR(callSystemExit)}, {CC "ticksNow", CC "()J", FN_PTR(ticksNow)}, - {CC "registerCompilerPhases", CC "([" STRING ")I", FN_PTR(registerCompilerPhases)}, + {CC "registerCompilerPhase", CC "(" STRING ")I", FN_PTR(registerCompilerPhase)}, {CC "notifyCompilerPhaseEvent", CC "(JIII)V", FN_PTR(notifyCompilerPhaseEvent)}, {CC "notifyCompilerInliningEvent", CC "(I" HS_RESOLVED_METHOD HS_RESOLVED_METHOD "ZLjava/lang/String;I)V", FN_PTR(notifyCompilerInliningEvent)}, }; diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index a900859b667..b87314f9156 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -36,10 +36,12 @@ #include "runtime/jniHandles.inline.hpp" #include "runtime/javaCalls.hpp" #include "jvmci/jniAccessMark.inline.hpp" +#include "jvmci/jvmciCompiler.hpp" #include "jvmci/jvmciRuntime.hpp" -JVMCICompileState::JVMCICompileState(CompileTask* task): +JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler): _task(task), + _compiler(compiler), _retryable(true), _failure_reason(NULL), _failure_reason_on_C_heap(false) { @@ -51,6 +53,20 @@ JVMCICompileState::JVMCICompileState(CompileTask* task): _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0; _jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0; _target_method_is_old = _task != NULL && _task->method()->is_old(); + if (task->is_blocking()) { + task->set_blocking_jvmci_compile_state(this); + } +} + +// Update global JVMCI compilation ticks after 512 thread-local JVMCI compilation ticks. +// This mitigates the overhead of the atomic operation used for the global update. +#define THREAD_TICKS_PER_GLOBAL_TICKS (2 << 9) +#define THREAD_TICKS_PER_GLOBAL_TICKS_MASK (THREAD_TICKS_PER_GLOBAL_TICKS - 1) + +void JVMCICompileState::inc_compilation_ticks() { + if ((++_compilation_ticks & THREAD_TICKS_PER_GLOBAL_TICKS_MASK) == 0) { + _compiler->inc_global_compilation_ticks(); + } } bool JVMCICompileState::jvmti_state_changed() const { @@ -241,9 +257,9 @@ void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int l // Prints a pending exception (if any) and its stack trace. void JVMCIEnv::describe_pending_exception(bool clear) { - Thread* THREAD = Thread::current(); + JavaThread* THREAD = JavaThread::current(); if (!is_hotspot()) { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); if (jni()->ExceptionCheck()) { jthrowable ex = !clear ? jni()->ExceptionOccurred() : NULL; jni()->ExceptionDescribe(); @@ -253,7 +269,7 @@ void JVMCIEnv::describe_pending_exception(bool clear) { } } else { if (HAS_PENDING_EXCEPTION) { - JVMCIRuntime::describe_pending_hotspot_exception((JavaThread*) THREAD, clear); + JVMCIRuntime::describe_pending_hotspot_exception(THREAD, clear); } } } @@ -292,8 +308,9 @@ JVMCIEnv::~JVMCIEnv() { if (is_hotspot()) { // Nothing to do } else { - if (Thread::current()->is_Java_thread()) { - JavaThread* THREAD = JavaThread::current(); + Thread* thread = Thread::current(); + if (thread->is_Java_thread()) { + JavaThread* THREAD = thread->as_Java_thread(); if (HAS_PENDING_EXCEPTION) { Handle throwable = Handle(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; @@ -619,8 +636,8 @@ void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong compile_state, int id) { + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { - Thread* THREAD = Thread::current(); JavaCallArguments jargs; jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method))); @@ -634,7 +651,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtim vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(), @@ -647,14 +664,14 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtim } void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) { + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { - Thread* THREAD = Thread::current(); JavaCallArguments jargs; jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); JavaValue result(T_VOID); JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method()); } @@ -680,7 +697,7 @@ void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) { } JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaCallArguments jargs; JavaValue result(T_OBJECT); @@ -697,7 +714,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) { } JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaCallArguments jargs; JavaValue result(T_OBJECT); @@ -714,7 +731,7 @@ JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) { } JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaCallArguments jargs; jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); @@ -733,7 +750,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaCallArguments jargs; jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object))); @@ -757,7 +774,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaCallArguments jargs; jargs.push_int(kind); @@ -781,7 +798,7 @@ JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value } JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaCallArguments jargs; jargs.push_float(value); @@ -804,7 +821,7 @@ JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) { } JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaCallArguments jargs; jargs.push_double(value); @@ -885,7 +902,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, } JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) { - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); JVMCIObject methodObject = get_jvmci_method(method, JVMCI_CHECK_(JVMCIObject())); @@ -988,7 +1005,7 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) return method_object; } - Thread* THREAD = Thread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); jmetadata handle = _runtime->allocate_handle(method); jboolean exception = false; if (is_hotspot()) { @@ -1004,7 +1021,7 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) method_object = wrap((oop)result.get_jobject()); } } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(), JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(), (jlong) handle)); @@ -1031,7 +1048,7 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) } jlong pointer = (jlong) klass(); - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); JVMCIObject signature = create_string(klass->signature_name(), JVMCI_CHECK_(JVMCIObject())); jboolean exception = false; if (is_hotspot()) { @@ -1070,7 +1087,7 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC JVMCIObject cp_object; jmetadata handle = _runtime->allocate_handle(cp); jboolean exception = false; - JavaThread* THREAD = JavaThread::current(); + JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); if (is_hotspot()) { JavaValue result(T_OBJECT); JavaCallArguments args; diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index 333525d5d69..e59a3bde6e0 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -94,6 +94,7 @@ class JVMCICompileState : public ResourceObj { friend class JVMCIVMStructs; private: CompileTask* _task; + JVMCICompiler* _compiler; // Cache JVMTI state. Defined as bytes so that reading them from Java // via Unsafe is well defined (the C++ type for bool is implementation @@ -113,8 +114,13 @@ class JVMCICompileState : public ResourceObj { // with the mtJVMCI NMT flag. bool _failure_reason_on_C_heap; + // A value indicating compilation activity during the compilation. + // If successive calls to this method return a different value, then + // some degree of JVMCI compilation occurred between the calls. + jint _compilation_ticks; + public: - JVMCICompileState(CompileTask* task); + JVMCICompileState(CompileTask* task, JVMCICompiler* compiler); CompileTask* task() { return _task; } @@ -135,6 +141,9 @@ class JVMCICompileState : public ResourceObj { _failure_reason_on_C_heap = reason_on_C_heap; _retryable = retryable; } + + jint compilation_ticks() const { return _compilation_ticks; } + void inc_compilation_ticks(); }; @@ -284,7 +293,7 @@ class JVMCIEnv : public ResourceObj { JVMCIPrimitiveArray wrap(typeArrayOop obj) { assert(is_hotspot(), "must be"); return (JVMCIPrimitiveArray) wrap(JNIHandles::make_local(obj)); } public: - // Compiles a method with the JVMIC compiler. + // Compiles a method with the JVMCI compiler. // Caller must handle pending exception. JVMCIObject call_HotSpotJVMCIRuntime_compileMethod(JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong compile_state, int id); diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp index 290775278c0..dc6a9000da0 100644 --- a/src/hotspot/share/jvmci/jvmci_globals.cpp +++ b/src/hotspot/share/jvmci/jvmci_globals.cpp @@ -38,9 +38,9 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() { #ifndef PRODUCT #define APPLY_JVMCI_FLAGS(params3, params4) \ - JVMCI_FLAGS(params4, params3, params4, params3, params4, params3, params4, params4, IGNORE_RANGE, IGNORE_CONSTRAINT) -#define JVMCI_DECLARE_CHECK4(type, name, value, doc) bool name##checked = false; -#define JVMCI_DECLARE_CHECK3(type, name, doc) bool name##checked = false; + JVMCI_FLAGS(params4, params3, params4, params3, params4, IGNORE_RANGE, IGNORE_CONSTRAINT) +#define JVMCI_DECLARE_CHECK4(type, name, value, ...) bool name##checked = false; +#define JVMCI_DECLARE_CHECK3(type, name, ...) bool name##checked = false; #define JVMCI_FLAG_CHECKED(name) name##checked = true; APPLY_JVMCI_FLAGS(JVMCI_DECLARE_CHECK3, JVMCI_DECLARE_CHECK4) #else @@ -131,8 +131,8 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() { #endif // !COMPILER2 #ifndef PRODUCT -#define JVMCI_CHECK4(type, name, value, doc) assert(name##checked, #name " flag not checked"); -#define JVMCI_CHECK3(type, name, doc) assert(name##checked, #name " flag not checked"); +#define JVMCI_CHECK4(type, name, value, ...) assert(name##checked, #name " flag not checked"); +#define JVMCI_CHECK3(type, name, ...) assert(name##checked, #name " flag not checked"); // Ensures that all JVMCI flags are checked by this method. APPLY_JVMCI_FLAGS(JVMCI_CHECK3, JVMCI_CHECK4) #undef APPLY_JVMCI_FLAGS diff --git a/src/hotspot/share/jvmci/jvmci_globals.hpp b/src/hotspot/share/jvmci/jvmci_globals.hpp index f4ae52b8473..dd1a375c732 100644 --- a/src/hotspot/share/jvmci/jvmci_globals.hpp +++ b/src/hotspot/share/jvmci/jvmci_globals.hpp @@ -30,54 +30,51 @@ class fileStream; // -// Defines all global flags used by the JVMCI compiler. Only flags that need +// Declare all global flags used by the JVMCI compiler. Only flags that need // to be accessible to the JVMCI C++ code should be defined here. // -#define JVMCI_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ - notproduct, \ - range, \ - constraint) \ - \ - experimental(bool, EnableJVMCI, false, \ +#define JVMCI_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ + \ + product(bool, EnableJVMCI, false, EXPERIMENTAL, \ "Enable JVMCI") \ \ - experimental(bool, EnableJVMCIProduct, false, \ + product(bool, EnableJVMCIProduct, false, EXPERIMENTAL, \ "Allow JVMCI to be used in product mode. This alters a subset of "\ "JVMCI flags to be non-experimental, defaults UseJVMCICompiler " \ "and EnableJVMCI to true and defaults UseJVMCINativeLibrary " \ "to true if a JVMCI native library is available.") \ \ - experimental(bool, UseJVMCICompiler, false, \ + product(bool, UseJVMCICompiler, false, EXPERIMENTAL, \ "Use JVMCI as the default compiler. Defaults to true if " \ "EnableJVMCIProduct is true.") \ \ - experimental(bool, JVMCIPrintProperties, false, \ + product(bool, JVMCIPrintProperties, false, EXPERIMENTAL, \ "Prints properties used by the JVMCI compiler and exits") \ \ - experimental(bool, BootstrapJVMCI, false, \ + product(bool, BootstrapJVMCI, false, EXPERIMENTAL, \ "Bootstrap JVMCI before running Java main method. This " \ "initializes the compile queue with a small set of methods " \ "and processes the queue until it is empty. Combining this with " \ "-XX:-TieredCompilation makes JVMCI compile more of itself.") \ \ - experimental(bool, EagerJVMCI, false, \ + product(bool, EagerJVMCI, false, EXPERIMENTAL, \ "Force eager JVMCI initialization") \ \ - experimental(bool, PrintBootstrap, true, \ + product(bool, PrintBootstrap, true, EXPERIMENTAL, \ "Print JVMCI bootstrap progress and summary") \ \ - experimental(intx, JVMCIThreads, 1, \ + product(intx, JVMCIThreads, 1, EXPERIMENTAL, \ "Force number of JVMCI compiler threads to use. Ignored if " \ "UseJVMCICompiler is false.") \ range(1, max_jint) \ \ - experimental(intx, JVMCIHostThreads, 1, \ + product(intx, JVMCIHostThreads, 1, EXPERIMENTAL, \ "Force number of C1 compiler threads. Ignored if " \ "UseJVMCICompiler is false.") \ range(1, max_jint) \ @@ -90,56 +87,58 @@ class fileStream; NOT_COMPILER2(product(bool, ReduceInitialCardMarks, true, \ "Defer write barriers of young objects")) \ \ - experimental(intx, JVMCIEventLogLevel, 1, \ + product(intx, JVMCIEventLogLevel, 1, EXPERIMENTAL, \ "Event log level for JVMCI") \ range(0, 4) \ \ - experimental(intx, JVMCITraceLevel, 0, \ + product(intx, JVMCITraceLevel, 0, EXPERIMENTAL, \ "Trace level for JVMCI") \ range(0, 4) \ \ - experimental(intx, JVMCICounterSize, 0, \ + product(intx, JVMCICounterSize, 0, EXPERIMENTAL, \ "Reserved size for benchmark counters") \ range(0, 1000000) \ \ - experimental(bool, JVMCICountersExcludeCompiler, true, \ + product(bool, JVMCICountersExcludeCompiler, true, EXPERIMENTAL, \ "Exclude JVMCI compiler threads from benchmark counters") \ \ develop(bool, JVMCIUseFastLocking, true, \ "Use fast inlined locking code") \ \ - experimental(intx, JVMCINMethodSizeLimit, (80*K)*wordSize, \ + product(intx, JVMCINMethodSizeLimit, (80*K)*wordSize, EXPERIMENTAL, \ "Maximum size of a compiled method.") \ range(0, max_jint) \ \ - experimental(ccstr, JVMCILibPath, NULL, \ + product(ccstr, JVMCILibPath, NULL, EXPERIMENTAL, \ "LD path for loading the JVMCI shared library") \ \ - experimental(ccstr, JVMCILibDumpJNIConfig, NULL, \ + product(ccstr, JVMCILibDumpJNIConfig, NULL, EXPERIMENTAL, \ "Dumps to the given file a description of the classes, fields " \ "and methods the JVMCI shared library must provide") \ \ - experimental(bool, UseJVMCINativeLibrary, false, \ + product(bool, UseJVMCINativeLibrary, false, EXPERIMENTAL, \ "Execute JVMCI Java code from a shared library " \ "instead of loading it from class files and executing it " \ "on the HotSpot heap. Defaults to true if EnableJVMCIProduct is " \ "true and a JVMCI native library is available.") \ \ - NOT_COMPILER2(diagnostic(bool, UseMultiplyToLenIntrinsic, false, \ + NOT_COMPILER2(product(bool, UseMultiplyToLenIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.multiplyToLen()")) \ \ - NOT_COMPILER2(diagnostic(bool, UseSquareToLenIntrinsic, false, \ + NOT_COMPILER2(product(bool, UseSquareToLenIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.squareToLen()")) \ \ - NOT_COMPILER2(diagnostic(bool, UseMulAddIntrinsic, false, \ + NOT_COMPILER2(product(bool, UseMulAddIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.mulAdd()")) \ \ - NOT_COMPILER2(diagnostic(bool, UseMontgomeryMultiplyIntrinsic, false, \ + NOT_COMPILER2(product(bool, UseMontgomeryMultiplyIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.montgomeryMultiply()")) \ \ - NOT_COMPILER2(diagnostic(bool, UseMontgomerySquareIntrinsic, false, \ + NOT_COMPILER2(product(bool, UseMontgomerySquareIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.montgomerySquare()")) +// end of JVMCI_FLAGS + // The base name for the shared library containing the JVMCI based compiler #define JVMCI_SHARED_LIBRARY_NAME "jvmcicompiler" diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 9c6c5279bfa..3a4b776d0a1 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -149,12 +149,6 @@ nonstatic_field(ExceptionTableElement, handler_pc, u2) \ nonstatic_field(ExceptionTableElement, catch_type_index, u2) \ \ - nonstatic_field(JVMFlag, _type, const char*) \ - nonstatic_field(JVMFlag, _name, const char*) \ - unchecked_nonstatic_field(JVMFlag, _addr, sizeof(void*)) \ - nonstatic_field(JVMFlag, _flags, JVMFlag::Flags) \ - static_field(JVMFlag, flags, JVMFlag*) \ - \ nonstatic_field(InstanceKlass, _fields, Array<u2>*) \ nonstatic_field(InstanceKlass, _constants, ConstantPool*) \ nonstatic_field(InstanceKlass, _init_state, u1) \ @@ -169,6 +163,7 @@ nonstatic_field(JVMCICompileState, _jvmti_can_access_local_variables, jbyte) \ nonstatic_field(JVMCICompileState, _jvmti_can_post_on_exceptions, jbyte) \ nonstatic_field(JVMCICompileState, _jvmti_can_pop_frame, jbyte) \ + nonstatic_field(JVMCICompileState, _compilation_ticks, jint) \ \ nonstatic_field(JavaThread, _threadObj, OopHandle) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ diff --git a/src/hotspot/share/memory/archiveBuilder.cpp b/src/hotspot/share/memory/archiveBuilder.cpp index 5401fd89a34..adf3b63b08c 100644 --- a/src/hotspot/share/memory/archiveBuilder.cpp +++ b/src/hotspot/share/memory/archiveBuilder.cpp @@ -23,11 +23,13 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderDataShared.hpp" #include "classfile/systemDictionaryShared.hpp" #include "logging/log.hpp" #include "logging/logMessage.hpp" #include "memory/archiveBuilder.hpp" #include "memory/archiveUtils.hpp" +#include "memory/cppVtables.hpp" #include "memory/dumpAllocStats.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" @@ -218,6 +220,11 @@ void ArchiveBuilder::gather_klasses_and_symbols() { log_info(cds)("Gathering classes and symbols ... "); GatherKlassesAndSymbols doit(this); iterate_roots(&doit, /*is_relocating_pointers=*/false); +#if INCLUDE_CDS_JAVA_HEAP + if (DumpSharedSpaces && MetaspaceShared::use_full_module_graph()) { + ClassLoaderDataShared::iterate_symbols(&doit); + } +#endif doit.finish(); log_info(cds)("Number of classes %d", _num_instance_klasses + _num_obj_array_klasses + _num_type_array_klasses); @@ -473,7 +480,7 @@ void ArchiveBuilder::make_shallow_copy(DumpRegion *dump_region, SourceObjInfo* s memcpy(dest, src, bytes); - intptr_t* archived_vtable = MetaspaceShared::get_archived_cpp_vtable(ref->msotype(), (address)dest); + intptr_t* archived_vtable = CppVtables::get_archived_cpp_vtable(ref->msotype(), (address)dest); if (archived_vtable != NULL) { *(address*)dest = (address)archived_vtable; ArchivePtrMarker::mark_pointer((address*)dest); diff --git a/src/hotspot/share/memory/cppVtables.cpp b/src/hotspot/share/memory/cppVtables.cpp new file mode 100644 index 00000000000..914ea209196 --- /dev/null +++ b/src/hotspot/share/memory/cppVtables.cpp @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "logging/log.hpp" +#include "memory/archiveUtils.hpp" +#include "memory/cppVtables.hpp" +#include "memory/metaspaceShared.hpp" +#include "oops/instanceClassLoaderKlass.hpp" +#include "oops/instanceMirrorKlass.hpp" +#include "oops/instanceRefKlass.hpp" +#include "oops/methodData.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/typeArrayKlass.hpp" +#include "runtime/arguments.hpp" +#include "utilities/globalDefinitions.hpp" + +// Objects of the Metadata types (such as Klass and ConstantPool) have C++ vtables. +// (In GCC this is the field <Type>::_vptr, i.e., first word in the object.) +// +// Addresses of the vtables and the methods may be different across JVM runs, +// if libjvm.so is dynamically loaded at a different base address. +// +// To ensure that the Metadata objects in the CDS archive always have the correct vtable: +// +// + at dump time: we redirect the _vptr to point to our own vtables inside +// the CDS image +// + at run time: we clone the actual contents of the vtables from libjvm.so +// into our own tables. + +// Currently, the archive contain ONLY the following types of objects that have C++ vtables. +#define CPP_VTABLE_PATCH_TYPES_DO(f) \ + f(ConstantPool) \ + f(InstanceKlass) \ + f(InstanceClassLoaderKlass) \ + f(InstanceMirrorKlass) \ + f(InstanceRefKlass) \ + f(Method) \ + f(ObjArrayKlass) \ + f(TypeArrayKlass) + +class CppVtableInfo { + intptr_t _vtable_size; + intptr_t _cloned_vtable[1]; +public: + static int num_slots(int vtable_size) { + return 1 + vtable_size; // Need to add the space occupied by _vtable_size; + } + int vtable_size() { return int(uintx(_vtable_size)); } + void set_vtable_size(int n) { _vtable_size = intptr_t(n); } + intptr_t* cloned_vtable() { return &_cloned_vtable[0]; } + void zero() { memset(_cloned_vtable, 0, sizeof(intptr_t) * vtable_size()); } + // Returns the address of the next CppVtableInfo that can be placed immediately after this CppVtableInfo + static size_t byte_size(int vtable_size) { + CppVtableInfo i; + return pointer_delta(&i._cloned_vtable[vtable_size], &i, sizeof(u1)); + } +}; + +static inline intptr_t* vtable_of(Metadata* m) { + return *((intptr_t**)m); +} + +static inline DumpRegion* mc_region() { + return MetaspaceShared::misc_code_dump_space(); +} + +template <class T> class CppVtableCloner : public T { + static CppVtableInfo* _info; + + static int get_vtable_length(const char* name); + +public: + // Allocate and initialize the C++ vtable, starting from top, but do not go past end. + static intptr_t* allocate(const char* name); + + // Clone the vtable to ... + static intptr_t* clone_vtable(const char* name, CppVtableInfo* info); + + static void zero_vtable_clone() { + assert(DumpSharedSpaces, "dump-time only"); + _info->zero(); + } + + static bool is_valid_shared_object(const T* obj) { + intptr_t* vptr = *(intptr_t**)obj; + return vptr == _info->cloned_vtable(); + } + + static void init_orig_cpp_vtptr(int kind); +}; + +template <class T> CppVtableInfo* CppVtableCloner<T>::_info = NULL; + +template <class T> +intptr_t* CppVtableCloner<T>::allocate(const char* name) { + assert(is_aligned(mc_region()->top(), sizeof(intptr_t)), "bad alignment"); + int n = get_vtable_length(name); + _info = (CppVtableInfo*)mc_region()->allocate(CppVtableInfo::byte_size(n), sizeof(intptr_t)); + _info->set_vtable_size(n); + + intptr_t* p = clone_vtable(name, _info); + assert((char*)p == mc_region()->top(), "must be"); + + return _info->cloned_vtable(); +} + +template <class T> +intptr_t* CppVtableCloner<T>::clone_vtable(const char* name, CppVtableInfo* info) { + if (!DumpSharedSpaces) { + assert(_info == 0, "_info is initialized only at dump time"); + _info = info; // Remember it -- it will be used by MetaspaceShared::is_valid_shared_method() + } + T tmp; // Allocate temporary dummy metadata object to get to the original vtable. + int n = info->vtable_size(); + intptr_t* srcvtable = vtable_of(&tmp); + intptr_t* dstvtable = info->cloned_vtable(); + + // We already checked (and, if necessary, adjusted n) when the vtables were allocated, so we are + // safe to do memcpy. + log_debug(cds, vtables)("Copying %3d vtable entries for %s", n, name); + memcpy(dstvtable, srcvtable, sizeof(intptr_t) * n); + return dstvtable + n; +} + +// To determine the size of the vtable for each type, we use the following +// trick by declaring 2 subclasses: +// +// class CppVtableTesterA: public InstanceKlass {virtual int last_virtual_method() {return 1;} }; +// class CppVtableTesterB: public InstanceKlass {virtual void* last_virtual_method() {return NULL}; }; +// +// CppVtableTesterA and CppVtableTesterB's vtables have the following properties: +// - Their size (N+1) is exactly one more than the size of InstanceKlass's vtable (N) +// - The first N entries have are exactly the same as in InstanceKlass's vtable. +// - Their last entry is different. +// +// So to determine the value of N, we just walk CppVtableTesterA and CppVtableTesterB's tables +// and find the first entry that's different. +// +// This works on all C++ compilers supported by Oracle, but you may need to tweak it for more +// esoteric compilers. + +template <class T> class CppVtableTesterB: public T { +public: + virtual int last_virtual_method() {return 1;} +}; + +template <class T> class CppVtableTesterA : public T { +public: + virtual void* last_virtual_method() { + // Make this different than CppVtableTesterB::last_virtual_method so the C++ + // compiler/linker won't alias the two functions. + return NULL; + } +}; + +template <class T> +int CppVtableCloner<T>::get_vtable_length(const char* name) { + CppVtableTesterA<T> a; + CppVtableTesterB<T> b; + + intptr_t* avtable = vtable_of(&a); + intptr_t* bvtable = vtable_of(&b); + + // Start at slot 1, because slot 0 may be RTTI (on Solaris/Sparc) + int vtable_len = 1; + for (; ; vtable_len++) { + if (avtable[vtable_len] != bvtable[vtable_len]) { + break; + } + } + log_debug(cds, vtables)("Found %3d vtable entries for %s", vtable_len, name); + + return vtable_len; +} + +#define ALLOC_CPP_VTABLE_CLONE(c) \ + _cloned_cpp_vtptrs[c##_Kind] = CppVtableCloner<c>::allocate(#c); \ + ArchivePtrMarker::mark_pointer(&_cloned_cpp_vtptrs[c##_Kind]); + +#define CLONE_CPP_VTABLE(c) \ + p = CppVtableCloner<c>::clone_vtable(#c, (CppVtableInfo*)p); + +#define ZERO_CPP_VTABLE(c) \ + CppVtableCloner<c>::zero_vtable_clone(); + +#define INIT_ORIG_CPP_VTPTRS(c) \ + CppVtableCloner<c>::init_orig_cpp_vtptr(c##_Kind); + +#define DECLARE_CLONED_VTABLE_KIND(c) c ## _Kind, + +enum ClonedVtableKind { + // E.g., ConstantPool_Kind == 0, InstanceKlass_Kind == 1, etc. + CPP_VTABLE_PATCH_TYPES_DO(DECLARE_CLONED_VTABLE_KIND) + _num_cloned_vtable_kinds +}; + +// This is a map of all the original vtptrs. E.g., for +// ConstantPool *cp = new (...) ConstantPool(...) ; // a dynamically allocated constant pool +// the following holds true: +// _orig_cpp_vtptrs[ConstantPool_Kind] == ((intptr_t**)cp)[0] +static intptr_t* _orig_cpp_vtptrs[_num_cloned_vtable_kinds]; +static bool _orig_cpp_vtptrs_inited = false; + +template <class T> +void CppVtableCloner<T>::init_orig_cpp_vtptr(int kind) { + assert(kind < _num_cloned_vtable_kinds, "sanity"); + T tmp; // Allocate temporary dummy metadata object to get to the original vtable. + intptr_t* srcvtable = vtable_of(&tmp); + _orig_cpp_vtptrs[kind] = srcvtable; +} + +// This is the index of all the cloned vtables. E.g., for +// ConstantPool* cp = ....; // an archived constant pool +// InstanceKlass* ik = ....;// an archived class +// the following holds true: +// _cloned_cpp_vtptrs[ConstantPool_Kind] == ((intptr_t**)cp)[0] +// _cloned_cpp_vtptrs[InstanceKlass_Kind] == ((intptr_t**)ik)[0] +static intptr_t** _cloned_cpp_vtptrs = NULL; + +void CppVtables::allocate_cloned_cpp_vtptrs() { + assert(DumpSharedSpaces, "must"); + size_t vtptrs_bytes = _num_cloned_vtable_kinds * sizeof(intptr_t*); + _cloned_cpp_vtptrs = (intptr_t**)mc_region()->allocate(vtptrs_bytes, sizeof(intptr_t*)); +} + +void CppVtables::serialize_cloned_cpp_vtptrs(SerializeClosure* soc) { + soc->do_ptr((void**)&_cloned_cpp_vtptrs); +} + +intptr_t* CppVtables::get_archived_cpp_vtable(MetaspaceObj::Type msotype, address obj) { + if (!_orig_cpp_vtptrs_inited) { + CPP_VTABLE_PATCH_TYPES_DO(INIT_ORIG_CPP_VTPTRS); + _orig_cpp_vtptrs_inited = true; + } + + Arguments::assert_is_dumping_archive(); + int kind = -1; + switch (msotype) { + case MetaspaceObj::SymbolType: + case MetaspaceObj::TypeArrayU1Type: + case MetaspaceObj::TypeArrayU2Type: + case MetaspaceObj::TypeArrayU4Type: + case MetaspaceObj::TypeArrayU8Type: + case MetaspaceObj::TypeArrayOtherType: + case MetaspaceObj::ConstMethodType: + case MetaspaceObj::ConstantPoolCacheType: + case MetaspaceObj::AnnotationsType: + case MetaspaceObj::MethodCountersType: + case MetaspaceObj::RecordComponentType: + // These have no vtables. + break; + case MetaspaceObj::MethodDataType: + // We don't archive MethodData <-- should have been removed in removed_unsharable_info + ShouldNotReachHere(); + break; + default: + for (kind = 0; kind < _num_cloned_vtable_kinds; kind ++) { + if (vtable_of((Metadata*)obj) == _orig_cpp_vtptrs[kind]) { + break; + } + } + if (kind >= _num_cloned_vtable_kinds) { + fatal("Cannot find C++ vtable for " INTPTR_FORMAT " -- you probably added" + " a new subtype of Klass or MetaData without updating CPP_VTABLE_PATCH_TYPES_DO", + p2i(obj)); + } + } + + if (kind >= 0) { + assert(kind < _num_cloned_vtable_kinds, "must be"); + return _cloned_cpp_vtptrs[kind]; + } else { + return NULL; + } +} + +// This can be called at both dump time and run time: +// - clone the contents of the c++ vtables into the space +// allocated by allocate_cpp_vtable_clones() +void CppVtables::clone_cpp_vtables(intptr_t* p) { + assert(DumpSharedSpaces || UseSharedSpaces, "sanity"); + CPP_VTABLE_PATCH_TYPES_DO(CLONE_CPP_VTABLE); +} + +void CppVtables::zero_cpp_vtable_clones_for_writing() { + assert(DumpSharedSpaces, "dump-time only"); + CPP_VTABLE_PATCH_TYPES_DO(ZERO_CPP_VTABLE); +} + +// Allocate and initialize the C++ vtables, starting from top, but do not go past end. +char* CppVtables::allocate_cpp_vtable_clones() { + char* cloned_vtables = mc_region()->top(); // This is the beginning of all the cloned vtables + + assert(DumpSharedSpaces, "dump-time only"); + // Layout (each slot is a intptr_t): + // [number of slots in the first vtable = n1] + // [ <n1> slots for the first vtable] + // [number of slots in the first second = n2] + // [ <n2> slots for the second vtable] + // ... + // The order of the vtables is the same as the CPP_VTAB_PATCH_TYPES_DO macro. + CPP_VTABLE_PATCH_TYPES_DO(ALLOC_CPP_VTABLE_CLONE); + + return cloned_vtables; +} + +bool CppVtables::is_valid_shared_method(const Method* m) { + assert(MetaspaceShared::is_in_shared_metaspace(m), "must be"); + return CppVtableCloner<Method>::is_valid_shared_object(m); +} diff --git a/src/hotspot/share/memory/cppVtables.hpp b/src/hotspot/share/memory/cppVtables.hpp new file mode 100644 index 00000000000..8604424c6fc --- /dev/null +++ b/src/hotspot/share/memory/cppVtables.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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_MEMORY_CPPVTABLES_HPP +#define SHARE_MEMORY_CPPVTABLES_HPP + +#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" + +class Method; +class SerializeClosure; + +// Support for C++ vtables in CDS archive. +class CppVtables : AllStatic { + static void patch_cpp_vtable_pointers(); +public: + static char* allocate_cpp_vtable_clones(); + static void allocate_cloned_cpp_vtptrs(); + static void clone_cpp_vtables(intptr_t* p); + static void zero_cpp_vtable_clones_for_writing(); + static intptr_t* get_archived_cpp_vtable(MetaspaceObj::Type msotype, address obj); + static void serialize_cloned_cpp_vtptrs(SerializeClosure* sc); + static bool is_valid_shared_method(const Method* m) NOT_CDS_RETURN_(false); +}; + +#endif // SHARE_MEMORY_CPPVTABLES_HPP diff --git a/src/hotspot/share/memory/dumpAllocStats.hpp b/src/hotspot/share/memory/dumpAllocStats.hpp index a0d3228de13..bb1e20b1191 100644 --- a/src/hotspot/share/memory/dumpAllocStats.hpp +++ b/src/hotspot/share/memory/dumpAllocStats.hpp @@ -39,6 +39,7 @@ class DumpAllocStats : public ResourceObj { f(SymbolBucket) \ f(StringHashentry) \ f(StringBucket) \ + f(ModulesNatives) \ f(Other) enum Type { @@ -74,6 +75,11 @@ class DumpAllocStats : public ResourceObj { _bytes [which][type] += byte_size; } + void record_modules(int byte_size, bool read_only) { + int which = (read_only) ? RO : RW; + _bytes [which][ModulesNativesType] += byte_size; + } + void record_other_type(int byte_size, bool read_only) { int which = (read_only) ? RO : RW; _bytes [which][OtherType] += byte_size; diff --git a/src/hotspot/share/memory/filemap.cpp b/src/hotspot/share/memory/filemap.cpp index a0ac1871c64..5137b823d6b 100644 --- a/src/hotspot/share/memory/filemap.cpp +++ b/src/hotspot/share/memory/filemap.cpp @@ -50,6 +50,7 @@ #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.inline.hpp" @@ -218,6 +219,7 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { _max_heap_size = MaxHeapSize; _narrow_klass_shift = CompressedKlassPointers::shift(); _use_optimized_module_handling = MetaspaceShared::use_optimized_module_handling(); + _use_full_module_graph = MetaspaceShared::use_full_module_graph(); // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's @@ -1845,6 +1847,7 @@ void FileMapInfo::map_heap_regions() { if (!HeapShared::open_archive_heap_region_mapped()) { assert(open_archive_heap_ranges == NULL && num_open_archive_heap_ranges == 0, "sanity"); + MetaspaceShared::disable_full_module_graph(); } } @@ -2179,7 +2182,12 @@ bool FileMapHeader::validate() { if (!_use_optimized_module_handling) { MetaspaceShared::disable_optimized_module_handling(); - log_info(cds)("use_optimized_module_handling disabled: archive was created without optimized module handling"); + log_info(cds)("optimized module handling: disabled because archive was created without optimized module handling"); + } + + if (!_use_full_module_graph) { + MetaspaceShared::disable_full_module_graph(); + log_info(cds)("full module graph: disabled because archive was created without full module graph"); } return true; diff --git a/src/hotspot/share/memory/filemap.hpp b/src/hotspot/share/memory/filemap.hpp index f3d0e2b4744..841cbd11b1b 100644 --- a/src/hotspot/share/memory/filemap.hpp +++ b/src/hotspot/share/memory/filemap.hpp @@ -233,6 +233,7 @@ class FileMapHeader: private CDSFileMapHeaderBase { bool _allow_archiving_with_java_agent; // setting of the AllowArchivingWithJavaAgent option bool _use_optimized_module_handling;// No module-relation VM options were specified, so we can skip // some expensive operations. + bool _use_full_module_graph; // Can we use the full archived module graph? size_t _ptrmap_size_in_bits; // Size of pointer relocation bitmap char* from_mapped_offset(size_t offset) const { diff --git a/src/hotspot/share/memory/heapShared.cpp b/src/hotspot/share/memory/heapShared.cpp index 6aaae27e184..dfd398db138 100644 --- a/src/hotspot/share/memory/heapShared.cpp +++ b/src/hotspot/share/memory/heapShared.cpp @@ -23,9 +23,13 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" +#include "classfile/classLoaderDataShared.hpp" #include "classfile/javaClasses.inline.hpp" +#include "classfile/moduleEntry.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" +#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmSymbols.hpp" #include "gc/shared/gcLocker.hpp" @@ -45,6 +49,7 @@ #include "oops/fieldStreams.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/fieldDescriptor.inline.hpp" +#include "runtime/javaCalls.hpp" #include "runtime/safepointVerifiers.hpp" #include "utilities/bitMap.inline.hpp" #if INCLUDE_G1GC @@ -68,26 +73,35 @@ DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL; // region. Warning: Objects in the subgraphs should not have reference fields // assigned at runtime. static ArchivableStaticFieldInfo closed_archive_subgraph_entry_fields[] = { - {"java/lang/Integer$IntegerCache", "archivedCache"}, - {"java/lang/Long$LongCache", "archivedCache"}, - {"java/lang/Byte$ByteCache", "archivedCache"}, - {"java/lang/Short$ShortCache", "archivedCache"}, - {"java/lang/Character$CharacterCache", "archivedCache"}, - {"java/util/jar/Attributes$Name", "KNOWN_NAMES"}, - {"sun/util/locale/BaseLocale", "constantBaseLocales"}, + {"java/lang/Integer$IntegerCache", "archivedCache"}, + {"java/lang/Long$LongCache", "archivedCache"}, + {"java/lang/Byte$ByteCache", "archivedCache"}, + {"java/lang/Short$ShortCache", "archivedCache"}, + {"java/lang/Character$CharacterCache", "archivedCache"}, + {"java/util/jar/Attributes$Name", "KNOWN_NAMES"}, + {"sun/util/locale/BaseLocale", "constantBaseLocales"}, }; // Entry fields for subgraphs archived in the open archive heap region. static ArchivableStaticFieldInfo open_archive_subgraph_entry_fields[] = { - {"jdk/internal/module/ArchivedModuleGraph", "archivedModuleGraph"}, - {"java/util/ImmutableCollections", "archivedObjects"}, - {"java/lang/module/Configuration", "EMPTY_CONFIGURATION"}, - {"jdk/internal/math/FDBigInteger", "archivedCaches"}, + {"jdk/internal/module/ArchivedModuleGraph", "archivedModuleGraph"}, + {"java/util/ImmutableCollections", "archivedObjects"}, + {"java/lang/module/Configuration", "EMPTY_CONFIGURATION"}, + {"jdk/internal/math/FDBigInteger", "archivedCaches"}, +}; + +// Entry fields for subgraphs archived in the open archive heap region (full module graph). +static ArchivableStaticFieldInfo fmg_open_archive_subgraph_entry_fields[] = { + {"jdk/internal/loader/ArchivedClassLoaders", "archivedClassLoaders"}, + {"jdk/internal/module/ArchivedBootLayer", "archivedBootLayer"}, + {"java/lang/Module$ArchivedData", "archivedData"}, }; const static int num_closed_archive_subgraph_entry_fields = sizeof(closed_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo); const static int num_open_archive_subgraph_entry_fields = sizeof(open_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo); +const static int num_fmg_open_archive_subgraph_entry_fields = + sizeof(fmg_open_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo); //////////////////////////////////////////////////////////////// // @@ -108,6 +122,36 @@ unsigned HeapShared::oop_hash(oop const& p) { return hash; } +static void reset_states(oop obj, TRAPS) { + Handle h_obj(THREAD, obj); + InstanceKlass* klass = InstanceKlass::cast(obj->klass()); + TempNewSymbol method_name = SymbolTable::new_symbol("resetArchivedStates"); + Symbol* method_sig = vmSymbols::void_method_signature(); + + while (klass != NULL) { + Method* method = klass->find_method(method_name, method_sig); + if (method != NULL) { + assert(method->is_private(), "must be"); + if (log_is_enabled(Debug, cds)) { + ResourceMark rm(THREAD); + log_debug(cds)(" calling %s", method->name_and_sig_as_C_string()); + } + JavaValue result(T_VOID); + JavaCalls::call_special(&result, h_obj, klass, + method_name, method_sig, CHECK); + } + klass = klass->java_super(); + } +} + +void HeapShared::reset_archived_object_states(TRAPS) { + assert(DumpSharedSpaces, "dump-time only"); + log_debug(cds)("Resetting platform loader"); + reset_states(SystemDictionary::java_platform_loader(), THREAD); + log_debug(cds)("Resetting system loader"); + reset_states(SystemDictionary::java_system_loader(), THREAD); +} + HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = NULL; oop HeapShared::find_archived_heap_object(oop obj) { assert(DumpSharedSpaces, "dump-time only"); @@ -238,6 +282,10 @@ void HeapShared::archive_java_heap_objects(GrowableArray<MemRegion> *closed, log_info(cds)("Dumping objects to open archive heap region ..."); copy_open_archive_heap_objects(open); + if (MetaspaceShared::use_full_module_graph()) { + ClassLoaderDataShared::init_archived_oops(); + } + destroy_archived_object_cache(); } @@ -256,7 +304,9 @@ void HeapShared::copy_closed_archive_heap_objects( archive_object_subgraphs(closed_archive_subgraph_entry_fields, num_closed_archive_subgraph_entry_fields, - true /* is_closed_archive */, THREAD); + true /* is_closed_archive */, + false /* is_full_module_graph */, + THREAD); G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive, os::vm_allocation_granularity()); @@ -276,7 +326,15 @@ void HeapShared::copy_open_archive_heap_objects( archive_object_subgraphs(open_archive_subgraph_entry_fields, num_open_archive_subgraph_entry_fields, false /* is_closed_archive */, + false /* is_full_module_graph */, THREAD); + if (MetaspaceShared::use_full_module_graph()) { + archive_object_subgraphs(fmg_open_archive_subgraph_entry_fields, + num_fmg_open_archive_subgraph_entry_fields, + false /* is_closed_archive */, + true /* is_full_module_graph */, + THREAD); + } G1CollectedHeap::heap()->end_archive_alloc_range(open_archive, os::vm_allocation_granularity()); @@ -296,15 +354,22 @@ HeapShared::RunTimeKlassSubGraphInfoTable HeapShared::_run_time_subgraph_info_ // Get the subgraph_info for Klass k. A new subgraph_info is created if // there is no existing one for k. The subgraph_info records the relocated // Klass* of the original k. +KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_graph) { + assert(DumpSharedSpaces, "dump time only"); + bool created; + Klass* relocated_k = MetaspaceShared::get_relocated_klass(k); + KlassSubGraphInfo* info = + _dump_time_subgraph_info_table->put_if_absent(relocated_k, KlassSubGraphInfo(relocated_k, is_full_module_graph), + &created); + assert(created, "must not initialize twice"); + return info; +} + KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) { assert(DumpSharedSpaces, "dump time only"); Klass* relocated_k = MetaspaceShared::get_relocated_klass(k); KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k); - if (info == NULL) { - _dump_time_subgraph_info_table->put(relocated_k, KlassSubGraphInfo(relocated_k)); - info = _dump_time_subgraph_info_table->get(relocated_k); - ++ _dump_time_subgraph_info_table->_count; - } + assert(info != NULL, "must have been initialized"); return info; } @@ -384,6 +449,7 @@ void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) { _k = info->klass(); _entry_field_records = NULL; _subgraph_object_klasses = NULL; + _is_full_module_graph = info->is_full_module_graph(); // populate the entry fields GrowableArray<juint>* entry_fields = info->subgraph_entry_fields(); @@ -464,7 +530,7 @@ void HeapShared::serialize_subgraph_info_table_header(SerializeClosure* soc) { _run_time_subgraph_info_table.serialize_header(soc); } -void HeapShared::initialize_from_archived_subgraph(Klass* k) { +void HeapShared::initialize_from_archived_subgraph(Klass* k, TRAPS) { if (!open_archive_heap_region_mapped()) { return; // nothing to do } @@ -476,7 +542,9 @@ void HeapShared::initialize_from_archived_subgraph(Klass* k) { // Initialize from archived data. Currently this is done only // during VM initialization time. No lock is needed. if (record != NULL) { - Thread* THREAD = Thread::current(); + if (record->is_full_module_graph() && !MetaspaceShared::use_full_module_graph()) { + return; + } int i; // Load/link/initialize the klasses of the objects in the subgraph. @@ -628,6 +696,25 @@ void HeapShared::check_closed_archive_heap_region_object(InstanceKlass* k, } } +void HeapShared::check_module_oop(oop orig_module_obj) { + assert(DumpSharedSpaces, "must be"); + assert(java_lang_Module::is_instance(orig_module_obj), "must be"); + ModuleEntry* orig_module_ent = java_lang_Module::module_entry_raw(orig_module_obj); + if (orig_module_ent == NULL) { + // These special Module objects are created in Java code. They are not + // defined via Modules::define_module(), so they don't have a ModuleEntry: + // java.lang.Module::ALL_UNNAMED_MODULE + // java.lang.Module::EVERYONE_MODULE + // jdk.internal.loader.ClassLoaders$BootClassLoader::unnamedModule + assert(java_lang_Module::name(orig_module_obj) == NULL, "must be unnamed"); + log_info(cds, heap)("Module oop with No ModuleEntry* @[" PTR_FORMAT "]", p2i(orig_module_obj)); + } else { + ClassLoaderData* loader_data = orig_module_ent->loader_data(); + assert(loader_data->is_builtin_class_loader_data(), "must be"); + } +} + + // (1) If orig_obj has not been archived yet, archive it. // (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called), // trace all objects that are reachable from it, and make sure these objects are archived. @@ -695,6 +782,18 @@ oop HeapShared::archive_reachable_objects_from(int level, vm_exit(1); } } + + if (java_lang_Module::is_instance(orig_obj)) { + check_module_oop(orig_obj); + java_lang_Module::set_module_entry(archived_obj, NULL); + java_lang_Module::set_loader(archived_obj, NULL); + } else if (java_lang_ClassLoader::is_instance(orig_obj)) { + // class_data will be restored explicitly at run time. + guarantee(orig_obj == SystemDictionary::java_platform_loader() || + orig_obj == SystemDictionary::java_system_loader() || + java_lang_ClassLoader::loader_data_raw(orig_obj) == NULL, "must be"); + java_lang_ClassLoader::release_set_loader_data(archived_obj, NULL); + } } assert(archived_obj != NULL, "must be"); @@ -881,8 +980,9 @@ void HeapShared::set_has_been_seen_during_subgraph_recording(oop obj) { ++ _num_new_walked_objs; } -void HeapShared::start_recording_subgraph(InstanceKlass *k, const char* class_name) { +void HeapShared::start_recording_subgraph(InstanceKlass *k, const char* class_name, bool is_full_module_graph) { log_info(cds, heap)("Start recording subgraph(s) for archived fields in %s", class_name); + init_subgraph_info(k, is_full_module_graph); init_seen_objects_table(); _num_new_walked_objs = 0; _num_new_archived_objs = 0; @@ -959,6 +1059,11 @@ void HeapShared::init_subgraph_entry_fields(Thread* THREAD) { init_subgraph_entry_fields(open_archive_subgraph_entry_fields, num_open_archive_subgraph_entry_fields, THREAD); + if (MetaspaceShared::use_full_module_graph()) { + init_subgraph_entry_fields(fmg_open_archive_subgraph_entry_fields, + num_fmg_open_archive_subgraph_entry_fields, + THREAD); + } } void HeapShared::init_for_dumping(Thread* THREAD) { @@ -968,6 +1073,7 @@ void HeapShared::init_for_dumping(Thread* THREAD) { void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], int num, bool is_closed_archive, + bool is_full_module_graph, Thread* THREAD) { _num_total_subgraph_recordings = 0; _num_total_walked_objs = 0; @@ -985,7 +1091,7 @@ void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], for (i = 0; i < num; ) { ArchivableStaticFieldInfo* info = &fields[i]; const char* klass_name = info->klass_name; - start_recording_subgraph(info->klass, klass_name); + start_recording_subgraph(info->klass, klass_name, is_full_module_graph); // If you have specified consecutive fields of the same klass in // fields[], these will be archived in the same @@ -996,6 +1102,7 @@ void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], if (f->klass_name != klass_name) { break; } + archive_reachable_objects_from_static_field(f->klass, f->klass_name, f->offset, f->field_name, is_closed_archive, CHECK); diff --git a/src/hotspot/share/memory/heapShared.hpp b/src/hotspot/share/memory/heapShared.hpp index 40e37865d20..e0a827efe4e 100644 --- a/src/hotspot/share/memory/heapShared.hpp +++ b/src/hotspot/share/memory/heapShared.hpp @@ -66,10 +66,12 @@ class KlassSubGraphInfo: public CHeapObj<mtClass> { // is_closed_archive flag. GrowableArray<juint>* _subgraph_entry_fields; + bool _is_full_module_graph; public: - KlassSubGraphInfo(Klass* k) : + KlassSubGraphInfo(Klass* k, bool is_full_module_graph) : _k(k), _subgraph_object_klasses(NULL), - _subgraph_entry_fields(NULL) {} + _subgraph_entry_fields(NULL), + _is_full_module_graph(is_full_module_graph) {} ~KlassSubGraphInfo() { if (_subgraph_object_klasses != NULL) { delete _subgraph_object_klasses; @@ -93,6 +95,7 @@ class KlassSubGraphInfo: public CHeapObj<mtClass> { return _subgraph_object_klasses == NULL ? 0 : _subgraph_object_klasses->length(); } + bool is_full_module_graph() const { return _is_full_module_graph; } }; // An archived record of object sub-graphs reachable from static @@ -101,6 +104,7 @@ class KlassSubGraphInfo: public CHeapObj<mtClass> { class ArchivedKlassSubGraphInfoRecord { private: Klass* _k; + bool _is_full_module_graph; // contains pairs of field offset and value for each subgraph entry field Array<juint>* _entry_field_records; @@ -115,6 +119,7 @@ class ArchivedKlassSubGraphInfoRecord { Klass* klass() const { return _k; } Array<juint>* entry_field_records() const { return _entry_field_records; } Array<Klass*>* subgraph_object_klasses() const { return _subgraph_object_klasses; } + bool is_full_module_graph() const { return _is_full_module_graph; } }; #endif // INCLUDE_CDS_JAVA_HEAP @@ -186,6 +191,7 @@ class HeapShared: AllStatic { static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[], int num, bool is_closed_archive, + bool is_full_module_graph, Thread* THREAD); // Archive object sub-graph starting from the given static field @@ -200,6 +206,7 @@ class HeapShared: AllStatic { static void verify_reachable_objects_from(oop obj, bool is_archived) PRODUCT_RETURN; static void verify_subgraph_from(oop orig_obj) PRODUCT_RETURN; + static KlassSubGraphInfo* init_subgraph_info(Klass *k, bool is_full_module_graph); static KlassSubGraphInfo* get_subgraph_info(Klass *k); static void init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[], @@ -239,13 +246,17 @@ class HeapShared: AllStatic { static int _num_total_recorded_klasses; static int _num_total_verifications; - static void start_recording_subgraph(InstanceKlass *k, const char* klass_name); + static void start_recording_subgraph(InstanceKlass *k, const char* klass_name, + bool is_full_module_graph); static void done_recording_subgraph(InstanceKlass *k, const char* klass_name); static bool has_been_seen_during_subgraph_recording(oop obj); static void set_has_been_seen_during_subgraph_recording(oop obj); + static void check_module_oop(oop orig_module_obj); + public: + static void reset_archived_object_states(TRAPS); static void create_archived_object_cache() { _archived_object_cache = new (ResourceObj::C_HEAP, mtClass)ArchivedObjectCache(); @@ -321,7 +332,7 @@ class HeapShared: AllStatic { inline static bool is_archived_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false); - static void initialize_from_archived_subgraph(Klass* k) NOT_CDS_JAVA_HEAP_RETURN; + static void initialize_from_archived_subgraph(Klass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN; // NarrowOops stored in the CDS archive may use a different encoding scheme // than CompressedOops::{base,shift} -- see FileMapInfo::map_heap_regions_impl. diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 9f5a36bbdf9..bf8a21f40ca 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -42,6 +42,7 @@ #include "oops/compressedOops.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/init.hpp" #include "services/memTracker.hpp" #include "utilities/copy.hpp" diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index d2a20447c3f..c80e1b108b9 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderDataGraph.hpp" +#include "classfile/classLoaderDataShared.hpp" #include "classfile/classListParser.hpp" #include "classfile/classLoaderExt.hpp" #include "classfile/loaderConstraints.hpp" @@ -40,6 +41,8 @@ #include "logging/logMessage.hpp" #include "memory/archiveBuilder.hpp" #include "memory/archiveUtils.inline.hpp" +#include "memory/cppVtables.hpp" +#include "memory/dumpAllocStats.hpp" #include "memory/dynamicArchive.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.inline.hpp" @@ -49,15 +52,10 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/compressedOops.inline.hpp" -#include "oops/instanceClassLoaderKlass.hpp" #include "oops/instanceMirrorKlass.hpp" -#include "oops/instanceRefKlass.hpp" -#include "oops/methodData.hpp" -#include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.hpp" -#include "oops/typeArrayKlass.hpp" #include "runtime/handles.inline.hpp" #include "runtime/os.hpp" #include "runtime/safepointVerifiers.hpp" @@ -87,6 +85,7 @@ void* MetaspaceShared::_shared_metaspace_static_top = NULL; intx MetaspaceShared::_relocation_delta; char* MetaspaceShared::_requested_base_address; bool MetaspaceShared::_use_optimized_module_handling = true; +bool MetaspaceShared::_use_full_module_graph = true; // The CDS archive is divided into the following regions: // mc - misc code (the method entry trampolines, c++ vtables) @@ -151,6 +150,10 @@ char* MetaspaceShared::read_only_space_alloc(size_t num_bytes) { return _ro_region.allocate(num_bytes); } +char* MetaspaceShared::read_write_space_alloc(size_t num_bytes) { + return _rw_region.allocate(num_bytes); +} + size_t MetaspaceShared::reserved_space_alignment() { return os::vm_allocation_granularity(); } static bool shared_base_valid(char* shared_base) { @@ -497,9 +500,11 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { SystemDictionaryShared::serialize_well_known_klasses(soc); soc->do_tag(--tag); - serialize_cloned_cpp_vtptrs(soc); + CppVtables::serialize_cloned_cpp_vtptrs(soc); soc->do_tag(--tag); + CDS_JAVA_HEAP_ONLY(ClassLoaderDataShared::serialize(soc)); + soc->do_tag(666); } @@ -607,297 +612,6 @@ void MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread } } -// Objects of the Metadata types (such as Klass and ConstantPool) have C++ vtables. -// (In GCC this is the field <Type>::_vptr, i.e., first word in the object.) -// -// Addresses of the vtables and the methods may be different across JVM runs, -// if libjvm.so is dynamically loaded at a different base address. -// -// To ensure that the Metadata objects in the CDS archive always have the correct vtable: -// -// + at dump time: we redirect the _vptr to point to our own vtables inside -// the CDS image -// + at run time: we clone the actual contents of the vtables from libjvm.so -// into our own tables. - -// Currently, the archive contain ONLY the following types of objects that have C++ vtables. -#define CPP_VTABLE_PATCH_TYPES_DO(f) \ - f(ConstantPool) \ - f(InstanceKlass) \ - f(InstanceClassLoaderKlass) \ - f(InstanceMirrorKlass) \ - f(InstanceRefKlass) \ - f(Method) \ - f(ObjArrayKlass) \ - f(TypeArrayKlass) - -class CppVtableInfo { - intptr_t _vtable_size; - intptr_t _cloned_vtable[1]; -public: - static int num_slots(int vtable_size) { - return 1 + vtable_size; // Need to add the space occupied by _vtable_size; - } - int vtable_size() { return int(uintx(_vtable_size)); } - void set_vtable_size(int n) { _vtable_size = intptr_t(n); } - intptr_t* cloned_vtable() { return &_cloned_vtable[0]; } - void zero() { memset(_cloned_vtable, 0, sizeof(intptr_t) * vtable_size()); } - // Returns the address of the next CppVtableInfo that can be placed immediately after this CppVtableInfo - static size_t byte_size(int vtable_size) { - CppVtableInfo i; - return pointer_delta(&i._cloned_vtable[vtable_size], &i, sizeof(u1)); - } -}; - -static inline intptr_t* vtable_of(Metadata* m) { - return *((intptr_t**)m); -} - -template <class T> class CppVtableCloner : public T { - static CppVtableInfo* _info; - - static int get_vtable_length(const char* name); - -public: - // Allocate and initialize the C++ vtable, starting from top, but do not go past end. - static intptr_t* allocate(const char* name); - - // Clone the vtable to ... - static intptr_t* clone_vtable(const char* name, CppVtableInfo* info); - - static void zero_vtable_clone() { - assert(DumpSharedSpaces, "dump-time only"); - _info->zero(); - } - - static bool is_valid_shared_object(const T* obj) { - intptr_t* vptr = *(intptr_t**)obj; - return vptr == _info->cloned_vtable(); - } - - static void init_orig_cpp_vtptr(int kind); -}; - -template <class T> CppVtableInfo* CppVtableCloner<T>::_info = NULL; - -template <class T> -intptr_t* CppVtableCloner<T>::allocate(const char* name) { - assert(is_aligned(_mc_region.top(), sizeof(intptr_t)), "bad alignment"); - int n = get_vtable_length(name); - _info = (CppVtableInfo*)_mc_region.allocate(CppVtableInfo::byte_size(n), sizeof(intptr_t)); - _info->set_vtable_size(n); - - intptr_t* p = clone_vtable(name, _info); - assert((char*)p == _mc_region.top(), "must be"); - - return _info->cloned_vtable(); -} - -template <class T> -intptr_t* CppVtableCloner<T>::clone_vtable(const char* name, CppVtableInfo* info) { - if (!DumpSharedSpaces) { - assert(_info == 0, "_info is initialized only at dump time"); - _info = info; // Remember it -- it will be used by MetaspaceShared::is_valid_shared_method() - } - T tmp; // Allocate temporary dummy metadata object to get to the original vtable. - int n = info->vtable_size(); - intptr_t* srcvtable = vtable_of(&tmp); - intptr_t* dstvtable = info->cloned_vtable(); - - // We already checked (and, if necessary, adjusted n) when the vtables were allocated, so we are - // safe to do memcpy. - log_debug(cds, vtables)("Copying %3d vtable entries for %s", n, name); - memcpy(dstvtable, srcvtable, sizeof(intptr_t) * n); - return dstvtable + n; -} - -// To determine the size of the vtable for each type, we use the following -// trick by declaring 2 subclasses: -// -// class CppVtableTesterA: public InstanceKlass {virtual int last_virtual_method() {return 1;} }; -// class CppVtableTesterB: public InstanceKlass {virtual void* last_virtual_method() {return NULL}; }; -// -// CppVtableTesterA and CppVtableTesterB's vtables have the following properties: -// - Their size (N+1) is exactly one more than the size of InstanceKlass's vtable (N) -// - The first N entries have are exactly the same as in InstanceKlass's vtable. -// - Their last entry is different. -// -// So to determine the value of N, we just walk CppVtableTesterA and CppVtableTesterB's tables -// and find the first entry that's different. -// -// This works on all C++ compilers supported by Oracle, but you may need to tweak it for more -// esoteric compilers. - -template <class T> class CppVtableTesterB: public T { -public: - virtual int last_virtual_method() {return 1;} -}; - -template <class T> class CppVtableTesterA : public T { -public: - virtual void* last_virtual_method() { - // Make this different than CppVtableTesterB::last_virtual_method so the C++ - // compiler/linker won't alias the two functions. - return NULL; - } -}; - -template <class T> -int CppVtableCloner<T>::get_vtable_length(const char* name) { - CppVtableTesterA<T> a; - CppVtableTesterB<T> b; - - intptr_t* avtable = vtable_of(&a); - intptr_t* bvtable = vtable_of(&b); - - // Start at slot 1, because slot 0 may be RTTI (on Solaris/Sparc) - int vtable_len = 1; - for (; ; vtable_len++) { - if (avtable[vtable_len] != bvtable[vtable_len]) { - break; - } - } - log_debug(cds, vtables)("Found %3d vtable entries for %s", vtable_len, name); - - return vtable_len; -} - -#define ALLOC_CPP_VTABLE_CLONE(c) \ - _cloned_cpp_vtptrs[c##_Kind] = CppVtableCloner<c>::allocate(#c); \ - ArchivePtrMarker::mark_pointer(&_cloned_cpp_vtptrs[c##_Kind]); - -#define CLONE_CPP_VTABLE(c) \ - p = CppVtableCloner<c>::clone_vtable(#c, (CppVtableInfo*)p); - -#define ZERO_CPP_VTABLE(c) \ - CppVtableCloner<c>::zero_vtable_clone(); - -#define INIT_ORIG_CPP_VTPTRS(c) \ - CppVtableCloner<c>::init_orig_cpp_vtptr(c##_Kind); - -#define DECLARE_CLONED_VTABLE_KIND(c) c ## _Kind, - -enum ClonedVtableKind { - // E.g., ConstantPool_Kind == 0, InstanceKlass_Kind == 1, etc. - CPP_VTABLE_PATCH_TYPES_DO(DECLARE_CLONED_VTABLE_KIND) - _num_cloned_vtable_kinds -}; - -// This is a map of all the original vtptrs. E.g., for -// ConstantPool *cp = new (...) ConstantPool(...) ; // a dynamically allocated constant pool -// the following holds true: -// _orig_cpp_vtptrs[ConstantPool_Kind] == ((intptr_t**)cp)[0] -static intptr_t* _orig_cpp_vtptrs[_num_cloned_vtable_kinds]; -static bool _orig_cpp_vtptrs_inited = false; - -template <class T> -void CppVtableCloner<T>::init_orig_cpp_vtptr(int kind) { - assert(kind < _num_cloned_vtable_kinds, "sanity"); - T tmp; // Allocate temporary dummy metadata object to get to the original vtable. - intptr_t* srcvtable = vtable_of(&tmp); - _orig_cpp_vtptrs[kind] = srcvtable; -} - -// This is the index of all the cloned vtables. E.g., for -// ConstantPool* cp = ....; // an archived constant pool -// InstanceKlass* ik = ....;// an archived class -// the following holds true: -// _cloned_cpp_vtptrs[ConstantPool_Kind] == ((intptr_t**)cp)[0] -// _cloned_cpp_vtptrs[InstanceKlass_Kind] == ((intptr_t**)ik)[0] -static intptr_t** _cloned_cpp_vtptrs = NULL; - -void MetaspaceShared::allocate_cloned_cpp_vtptrs() { - assert(DumpSharedSpaces, "must"); - size_t vtptrs_bytes = _num_cloned_vtable_kinds * sizeof(intptr_t*); - _cloned_cpp_vtptrs = (intptr_t**)_mc_region.allocate(vtptrs_bytes, sizeof(intptr_t*)); -} - -void MetaspaceShared::serialize_cloned_cpp_vtptrs(SerializeClosure* soc) { - soc->do_ptr((void**)&_cloned_cpp_vtptrs); -} - -intptr_t* MetaspaceShared::get_archived_cpp_vtable(MetaspaceObj::Type msotype, address obj) { - if (!_orig_cpp_vtptrs_inited) { - CPP_VTABLE_PATCH_TYPES_DO(INIT_ORIG_CPP_VTPTRS); - _orig_cpp_vtptrs_inited = true; - } - - Arguments::assert_is_dumping_archive(); - int kind = -1; - switch (msotype) { - case MetaspaceObj::SymbolType: - case MetaspaceObj::TypeArrayU1Type: - case MetaspaceObj::TypeArrayU2Type: - case MetaspaceObj::TypeArrayU4Type: - case MetaspaceObj::TypeArrayU8Type: - case MetaspaceObj::TypeArrayOtherType: - case MetaspaceObj::ConstMethodType: - case MetaspaceObj::ConstantPoolCacheType: - case MetaspaceObj::AnnotationsType: - case MetaspaceObj::MethodCountersType: - case MetaspaceObj::RecordComponentType: - // These have no vtables. - break; - case MetaspaceObj::MethodDataType: - // We don't archive MethodData <-- should have been removed in removed_unsharable_info - ShouldNotReachHere(); - break; - default: - for (kind = 0; kind < _num_cloned_vtable_kinds; kind ++) { - if (vtable_of((Metadata*)obj) == _orig_cpp_vtptrs[kind]) { - break; - } - } - if (kind >= _num_cloned_vtable_kinds) { - fatal("Cannot find C++ vtable for " INTPTR_FORMAT " -- you probably added" - " a new subtype of Klass or MetaData without updating CPP_VTABLE_PATCH_TYPES_DO", - p2i(obj)); - } - } - - if (kind >= 0) { - assert(kind < _num_cloned_vtable_kinds, "must be"); - return _cloned_cpp_vtptrs[kind]; - } else { - return NULL; - } -} - -// This can be called at both dump time and run time: -// - clone the contents of the c++ vtables into the space -// allocated by allocate_cpp_vtable_clones() -void MetaspaceShared::clone_cpp_vtables(intptr_t* p) { - assert(DumpSharedSpaces || UseSharedSpaces, "sanity"); - CPP_VTABLE_PATCH_TYPES_DO(CLONE_CPP_VTABLE); -} - -void MetaspaceShared::zero_cpp_vtable_clones_for_writing() { - assert(DumpSharedSpaces, "dump-time only"); - CPP_VTABLE_PATCH_TYPES_DO(ZERO_CPP_VTABLE); -} - -// Allocate and initialize the C++ vtables, starting from top, but do not go past end. -char* MetaspaceShared::allocate_cpp_vtable_clones() { - char* cloned_vtables = _mc_region.top(); // This is the beginning of all the cloned vtables - - assert(DumpSharedSpaces, "dump-time only"); - // Layout (each slot is a intptr_t): - // [number of slots in the first vtable = n1] - // [ <n1> slots for the first vtable] - // [number of slots in the first second = n2] - // [ <n2> slots for the second vtable] - // ... - // The order of the vtables is the same as the CPP_VTAB_PATCH_TYPES_DO macro. - CPP_VTABLE_PATCH_TYPES_DO(ALLOC_CPP_VTABLE_CLONE); - - return cloned_vtables; -} - -bool MetaspaceShared::is_valid_shared_method(const Method* m) { - assert(is_in_shared_metaspace(m), "must be"); - return CppVtableCloner<Method>::is_valid_shared_object(m); -} - class VM_PopulateDumpSharedSpace: public VM_Operation { private: GrowableArray<MemRegion> *_closed_archive_heap_regions; @@ -1066,14 +780,33 @@ void VM_PopulateDumpSharedSpace::doit() { builder.gather_source_objs(); - MetaspaceShared::allocate_cloned_cpp_vtptrs(); + CppVtables::allocate_cloned_cpp_vtptrs(); char* cloned_vtables = _mc_region.top(); - MetaspaceShared::allocate_cpp_vtable_clones(); + CppVtables::allocate_cpp_vtable_clones(); - _mc_region.pack(&_rw_region); - builder.dump_rw_region(); - _rw_region.pack(&_ro_region); - builder.dump_ro_region(); + { + _mc_region.pack(&_rw_region); + builder.dump_rw_region(); +#if INCLUDE_CDS_JAVA_HEAP + if (MetaspaceShared::use_full_module_graph()) { + // Archive the ModuleEntry's and PackageEntry's of the 3 built-in loaders + char* start = _rw_region.top(); + ClassLoaderDataShared::allocate_archived_tables(); + ArchiveBuilder::alloc_stats()->record_modules(_rw_region.top() - start, /*read_only*/false); + } +#endif + } + { + _rw_region.pack(&_ro_region); + builder.dump_ro_region(); +#if INCLUDE_CDS_JAVA_HEAP + if (MetaspaceShared::use_full_module_graph()) { + char* start = _ro_region.top(); + ClassLoaderDataShared::init_archived_tables(); + ArchiveBuilder::alloc_stats()->record_modules(_ro_region.top() - start, /*read_only*/true); + } +#endif + } builder.relocate_pointers(); dump_shared_symbol_table(builder.symbols()); @@ -1090,7 +823,7 @@ void VM_PopulateDumpSharedSpace::doit() { // The vtable clones contain addresses of the current process. // We don't want to write these addresses into the archive. Same for i2i buffer. - MetaspaceShared::zero_cpp_vtable_clones_for_writing(); + CppVtables::zero_cpp_vtable_clones_for_writing(); memset(MetaspaceShared::i2i_entry_code_buffers(), 0, MetaspaceShared::i2i_entry_code_buffers_size()); @@ -1356,6 +1089,8 @@ void MetaspaceShared::preload_and_dump(TRAPS) { HeapShared::init_for_dumping(THREAD); + // exercise the manifest processing code to ensure classes used by CDS are always archived + SystemDictionaryShared::create_jar_manifest("Manifest-Version: 1.0\n", strlen("Manifest-Version: 1.0\n"), THREAD); // Rewrite and link classes log_info(cds)("Rewriting and linking classes ..."); @@ -1366,6 +1101,12 @@ void MetaspaceShared::preload_and_dump(TRAPS) { link_and_cleanup_shared_classes(CATCH); log_info(cds)("Rewriting and linking classes: done"); +#if INCLUDE_CDS_JAVA_HEAP + if (use_full_module_graph()) { + HeapShared::reset_archived_object_states(THREAD); + } +#endif + VM_PopulateDumpSharedSpace op; MutexLocker ml(THREAD, HeapShared::is_heap_object_archiving_allowed() ? Heap_lock : NULL); // needed by HeapShared::run_gc() @@ -1747,9 +1488,12 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File // map_heap_regions() compares the current narrow oop and klass encodings // with the archived ones, so it must be done after all encodings are determined. static_mapinfo->map_heap_regions(); + + disable_full_module_graph(); // Disabled temporarily for JDK-8253081 } }); - log_info(cds)("Using optimized module handling %s", MetaspaceShared::use_optimized_module_handling() ? "enabled" : "disabled"); + log_info(cds)("optimized module handling: %s", MetaspaceShared::use_optimized_module_handling() ? "enabled" : "disabled"); + log_info(cds)("full module graph: %s", MetaspaceShared::use_full_module_graph() ? "enabled" : "disabled"); } else { unmap_archive(static_mapinfo); unmap_archive(dynamic_mapinfo); @@ -1991,7 +1735,7 @@ void MetaspaceShared::initialize_shared_spaces() { _i2i_entry_code_buffers = static_mapinfo->i2i_entry_code_buffers(); _i2i_entry_code_buffers_size = static_mapinfo->i2i_entry_code_buffers_size(); char* buffer = static_mapinfo->cloned_vtables(); - clone_cpp_vtables((intptr_t*)buffer); + CppVtables::clone_cpp_vtables((intptr_t*)buffer); // Verify various attributes of the archive, plus initialize the // shared string/symbol tables @@ -2074,6 +1818,17 @@ intx MetaspaceShared::final_delta() { - intx(SharedBaseAddress); // .. but the base archive is mapped at here at dump time } +bool MetaspaceShared::use_full_module_graph() { + bool result = _use_optimized_module_handling && _use_full_module_graph && + (UseSharedSpaces || DumpSharedSpaces) && HeapShared::is_heap_object_archiving_allowed(); + if (result && UseSharedSpaces) { + // Classes used by the archived full module graph are loaded in JVMTI early phase. + assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()), + "CDS should be disabled if early class hooks are enabled"); + } + return result; +} + void MetaspaceShared::print_on(outputStream* st) { if (UseSharedSpaces || DumpSharedSpaces) { st->print("CDS archive(s) mapped at: "); diff --git a/src/hotspot/share/memory/metaspaceShared.hpp b/src/hotspot/share/memory/metaspaceShared.hpp index b2b65cd7332..8ffd20f5c45 100644 --- a/src/hotspot/share/memory/metaspaceShared.hpp +++ b/src/hotspot/share/memory/metaspaceShared.hpp @@ -78,6 +78,7 @@ class MetaspaceShared : AllStatic { static intx _relocation_delta; static char* _requested_base_address; static bool _use_optimized_module_handling; + static bool _use_full_module_graph; public: enum { // core archive spaces @@ -167,13 +168,6 @@ class MetaspaceShared : AllStatic { static bool is_shared_dynamic(void* p) NOT_CDS_RETURN_(false); - static char* allocate_cpp_vtable_clones(); - static void clone_cpp_vtables(intptr_t* p); - static void zero_cpp_vtable_clones_for_writing(); - static void patch_cpp_vtable_pointers(); - static void serialize_cloned_cpp_vtptrs(SerializeClosure* sc); - - static bool is_valid_shared_method(const Method* m) NOT_CDS_RETURN_(false); static void serialize(SerializeClosure* sc) NOT_CDS_RETURN; static MetaspaceSharedStats* stats() { @@ -215,17 +209,22 @@ class MetaspaceShared : AllStatic { // Allocate a block of memory from the "mc" or "ro" regions. static char* misc_code_space_alloc(size_t num_bytes); static char* read_only_space_alloc(size_t num_bytes); + static char* read_write_space_alloc(size_t num_bytes); template <typename T> static Array<T>* new_ro_array(int length) { -#if INCLUDE_CDS size_t byte_size = Array<T>::byte_sizeof(length, sizeof(T)); Array<T>* array = (Array<T>*)read_only_space_alloc(byte_size); array->initialize(length); return array; -#else - return NULL; -#endif + } + + template <typename T> + static Array<T>* new_rw_array(int length) { + size_t byte_size = Array<T>::byte_sizeof(length, sizeof(T)); + Array<T>* array = (Array<T>*)read_write_space_alloc(byte_size); + array->initialize(length); + return array; } template <typename T> @@ -246,8 +245,6 @@ class MetaspaceShared : AllStatic { static Klass* get_relocated_klass(Klass *k, bool is_final=false); - static void allocate_cloned_cpp_vtptrs(); - static intptr_t* get_archived_cpp_vtable(MetaspaceObj::Type msotype, address obj); static void initialize_ptr_marker(CHeapBitMap* ptrmap); // This is the base address as specified by -XX:SharedBaseAddress during -Xshare:dump. @@ -270,9 +267,13 @@ class MetaspaceShared : AllStatic { GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps); // Can we skip some expensive operations related to modules? - static bool use_optimized_module_handling() { return _use_optimized_module_handling; } + static bool use_optimized_module_handling() { return NOT_CDS(false) CDS_ONLY(_use_optimized_module_handling); } static void disable_optimized_module_handling() { _use_optimized_module_handling = false; } + // Can we use the full archived modue graph? + static bool use_full_module_graph() NOT_CDS_RETURN_(false); + static void disable_full_module_graph() { _use_full_module_graph = false; } + private: #if INCLUDE_CDS static void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, diff --git a/src/hotspot/share/memory/padded.hpp b/src/hotspot/share/memory/padded.hpp index c51d1e7a63b..08003613609 100644 --- a/src/hotspot/share/memory/padded.hpp +++ b/src/hotspot/share/memory/padded.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 +34,7 @@ // when the start address is not a multiple of alignment; the second maintains // alignment of starting addresses that happen to be a multiple. #define PADDING_SIZE(type, alignment) \ - ((alignment) + align_up_(sizeof(type), (alignment))) + ((alignment) + align_up(sizeof(type), (alignment))) // Templates to create a subclass padded to avoid cache line sharing. These are // effective only when applied to derived-most (leaf) classes. @@ -69,7 +69,7 @@ class PaddedEndImpl<T, /*pad_size*/ 0> : public T { // No padding. }; -#define PADDED_END_SIZE(type, alignment) (align_up_(sizeof(type), (alignment)) - sizeof(type)) +#define PADDED_END_SIZE(type, alignment) (align_up(sizeof(type), (alignment)) - sizeof(type)) // More memory conservative implementation of Padded. The subclass adds the // minimal amount of padding needed to make the size of the objects be aligned. diff --git a/src/hotspot/share/memory/padded.inline.hpp b/src/hotspot/share/memory/padded.inline.hpp index 939bf7b69db..d698f5ee1b3 100644 --- a/src/hotspot/share/memory/padded.inline.hpp +++ b/src/hotspot/share/memory/padded.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ template <class T, MEMFLAGS flags, size_t alignment> PaddedEnd<T>* PaddedArray<T, flags, alignment>::create_unfreeable(uint length) { // Check that the PaddedEnd class works as intended. - STATIC_ASSERT(is_aligned_(sizeof(PaddedEnd<T>), alignment)); + STATIC_ASSERT(is_aligned(sizeof(PaddedEnd<T>), alignment)); // Allocate a chunk of memory large enough to allow for some alignment. void* chunk = AllocateHeap(length * sizeof(PaddedEnd<T, alignment>) + alignment, flags); diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 0555dfa04d1..ae2ad7d6e1d 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -1031,26 +1031,6 @@ void Universe::print_heap_at_SIGBREAK() { } } -void Universe::print_heap_before_gc() { - LogTarget(Debug, gc, heap) lt; - if (lt.is_enabled()) { - LogStream ls(lt); - ls.print("Heap before GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections()); - ResourceMark rm; - heap()->print_on(&ls); - } -} - -void Universe::print_heap_after_gc() { - LogTarget(Debug, gc, heap) lt; - if (lt.is_enabled()) { - LogStream ls(lt); - ls.print("Heap after GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections()); - ResourceMark rm; - heap()->print_on(&ls); - } -} - void Universe::initialize_verify_flags() { verify_flags = 0; const char delimiter[] = " ,"; diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index 4d80ec4df41..42b3e635ebb 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -357,8 +357,6 @@ class Universe: AllStatic { static int verify_count() { return _verify_count; } static void print_on(outputStream* st); static void print_heap_at_SIGBREAK(); - static void print_heap_before_gc(); - static void print_heap_after_gc(); // Change the number of dummy objects kept reachable by the full gc dummy // array; this should trigger relocation in a sliding compaction collector. diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index 7f88f0dcf50..cbb1a0427c7 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -29,6 +29,7 @@ #include "oops/compressedOops.hpp" #include "oops/markWord.hpp" #include "oops/oop.inline.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/os.inline.hpp" #include "services/memTracker.hpp" diff --git a/src/hotspot/share/metaprogramming/primitiveConversions.hpp b/src/hotspot/share/metaprogramming/primitiveConversions.hpp index 2d9fa6e3dbb..08806442bf4 100644 --- a/src/hotspot/share/metaprogramming/primitiveConversions.hpp +++ b/src/hotspot/share/metaprogramming/primitiveConversions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * 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,147 +25,102 @@ #ifndef SHARE_METAPROGRAMMING_PRIMITIVECONVERSIONS_HPP #define SHARE_METAPROGRAMMING_PRIMITIVECONVERSIONS_HPP -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "metaprogramming/enableIf.hpp" -#include "metaprogramming/integralConstant.hpp" -#include "metaprogramming/isFloatingPoint.hpp" -#include "metaprogramming/isIntegral.hpp" -#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" #include <type_traits> class PrimitiveConversions : public AllStatic { + + // True if types are the same size and either is integral. + template<typename To, typename From> + static constexpr bool check_cast() { + return (sizeof(To) == sizeof(From)) && + (std::is_integral<To>::value || std::is_integral<From>::value); + } + public: - // Return a value of type T with the same representation as x. + // template<typename To, typename From> To cast(From x) + // + // Return a value of type To with the same value representation as x. // - // T and U must be of the same size. + // To and From must be of the same size. // - // At least one of T or U must be an integral type. The other must - // be an integral, floating point, or pointer type. - template<typename T, typename U> static T cast(U x); + // At least one of To or From must be an integral type. The other must + // be an integral, enum, floating point, or pointer type. + + // integer -> integer + // Use static_cast for conversion. See C++14 4.7 Integral + // conversions. If To is signed and From unsigned, the result is + // implementation-defined. All supported platforms provide two's + // complement behavior, and that behavior is required by C++20. + // Using an lvalue to reference cast (see C++03 3.10/15) involves a + // reinterpret_cast, which prevents constexpr support. + template<typename To, typename From, + ENABLE_IF(sizeof(To) == sizeof(From)), + ENABLE_IF(std::is_integral<To>::value), + ENABLE_IF(std::is_integral<From>::value)> + static constexpr To cast(From x) { + return static_cast<To>(x); + } + + // integer -> enum, enum -> integer + // Use the enum's underlying type for integer -> integer cast. + template<typename To, typename From, + ENABLE_IF(check_cast<To, From>()), + ENABLE_IF(std::is_enum<To>::value)> + static constexpr To cast(From x) { + return static_cast<To>(cast<std::underlying_type_t<To>>(x)); + } + + template<typename To, typename From, + ENABLE_IF(check_cast<To, From>()), + ENABLE_IF(std::is_enum<From>::value)> + static constexpr To cast(From x) { + return cast<To>(static_cast<std::underlying_type_t<From>>(x)); + } + + // integer -> pointer, pointer -> integer + // Use reinterpret_cast, so no constexpr support. + template<typename To, typename From, + ENABLE_IF(check_cast<To, From>()), + ENABLE_IF(std::is_pointer<To>::value || std::is_pointer<From>::value)> + static To cast(From x) { + return reinterpret_cast<To>(x); + } + + // integer -> floating point, floating point -> integer + // Use the union trick. The union trick is technically UB, but is + // widely and well supported, producing good code. In some cases, + // such as gcc, that support is explicitly documented. Using memcpy + // is the correct method, but some compilers produce wretched code + // for that method, even at maximal optimization levels. Neither + // the union trick nor memcpy provides constexpr support. + template<typename To, typename From, + ENABLE_IF(check_cast<To, From>()), + ENABLE_IF(std::is_floating_point<To>::value || + std::is_floating_point<From>::value)> + static To cast(From x) { + union { From from; To to; } converter = { x }; + return converter.to; + } // Support thin wrappers over primitive types. - // If derived from TrueType, provides representational conversion + // If derived from std::true_type, provides representational conversion // from T to some other type. When true, must provide // - Value: typedef for T. // - Decayed: typedef for decayed type. // - static Decayed decay(T x): return value of type Decayed with - // the same representation as x. + // the same value representation as x. // - static T recover(Decayed x): return a value of type T with the - // same representation as x. - template<typename T> struct Translate : public FalseType {}; - -private: - - template<typename T, - typename U, - bool same_size = sizeof(T) == sizeof(U), - typename Enable = void> - struct Cast; - - template<typename T, typename U> static T cast_using_union(U x); -}; - -// Return an object of type T with the same value representation as x. -// -// T and U must be of the same size. It is expected that one of T and -// U is an integral type, and the other is an integral type, an enum type, -// or a floating point type. -// -// This implementation uses the "union trick", which seems to be the -// best of a bad set of options. Though technically undefined -// behavior, it is widely and well supported, producing good code. In -// some cases, such as gcc, that support is explicitly documented. -// -// Using memcpy is the correct method, but some compilers produce -// wretched code for that method, even at maximal optimization levels. -// -// Using static_cast is only possible for integral and enum types, not -// for floating point types. And for integral and enum conversions, -// static_cast has unspecified or implementation-defined behavior for -// some cases. C++11 <type_traits> can be used to avoid most or all -// of those unspecified or implementation-defined issues, though that -// may require multi-step conversions. -// -// Using reinterpret_cast of references has undefined behavior for -// many cases, and there is much less empirical basis for its use, as -// compared to the union trick. -template<typename T, typename U> -inline T PrimitiveConversions::cast_using_union(U x) { - STATIC_ASSERT(sizeof(T) == sizeof(U)); - union { T t; U u; }; - u = x; - return t; -} - -////////////////////////////////////////////////////////////////////////////// -// cast<T>(x) -// -// Cast<T, U, same_size, Enable> - -// Give an informative error if the sizes differ. -template<typename T, typename U> -struct PrimitiveConversions::Cast<T, U, false> { - STATIC_ASSERT(sizeof(T) == sizeof(U)); -}; - -// Conversion between integral types. -template<typename T, typename U> -struct PrimitiveConversions::Cast< - T, U, true, - typename EnableIf<IsIntegral<T>::value && IsIntegral<U>::value>::type> -{ - T operator()(U x) const { return cast_using_union<T>(x); } + // same value representation as x. + template<typename T> struct Translate : public std::false_type {}; }; -// Convert an enum or floating point value to an integer value. -template<typename T, typename U> -struct PrimitiveConversions::Cast< - T, U, true, - typename EnableIf<IsIntegral<T>::value && - (std::is_enum<U>::value || - IsFloatingPoint<U>::value)>::type> -{ - T operator()(U x) const { return cast_using_union<T>(x); } -}; - -// Convert an integer to an enum or floating point value. -template<typename T, typename U> -struct PrimitiveConversions::Cast< - T, U, true, - typename EnableIf<IsIntegral<U>::value && - (std::is_enum<T>::value || - IsFloatingPoint<T>::value)>::type> -{ - T operator()(U x) const { return cast_using_union<T>(x); } -}; - -// Convert a pointer to an integral value. -template<typename T, typename U> -struct PrimitiveConversions::Cast< - T, U*, true, - typename EnableIf<IsIntegral<T>::value>::type> -{ - T operator()(U* x) const { return reinterpret_cast<T>(x); } -}; - -// Convert an integral value to a pointer. -template<typename T, typename U> -struct PrimitiveConversions::Cast< - T*, U, true, - typename EnableIf<IsIntegral<U>::value>::type> -{ - T* operator()(U x) const { return reinterpret_cast<T*>(x); } -}; - -template<typename T, typename U> -inline T PrimitiveConversions::cast(U x) { - return Cast<T, U>()(x); -} - // jfloat and jdouble translation to integral types template<> -struct PrimitiveConversions::Translate<jdouble> : public TrueType { +struct PrimitiveConversions::Translate<jdouble> : public std::true_type { typedef double Value; typedef int64_t Decayed; @@ -174,7 +129,7 @@ struct PrimitiveConversions::Translate<jdouble> : public TrueType { }; template<> -struct PrimitiveConversions::Translate<jfloat> : public TrueType { +struct PrimitiveConversions::Translate<jfloat> : public std::true_type { typedef float Value; typedef int32_t Decayed; diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 0f650fdca4f..f76a75fba4e 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -492,8 +492,7 @@ void ConstantPool::trace_class_resolution(const constantPoolHandle& this_cp, Kla Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, bool save_resolution_error, TRAPS) { - assert(THREAD->is_Java_thread(), "must be a Java thread"); - JavaThread* javaThread = (JavaThread*)THREAD; + JavaThread* javaThread = THREAD->as_Java_thread(); // A resolved constantPool entry will contain a Klass*, otherwise a Symbol*. // It is not safe to rely on the tag bit's here, since we don't have a lock, and diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index 7e5282dfba5..783dff8a539 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -495,7 +495,7 @@ class ConstantPool : public Metadata { // a String entry. // This can happen if the user patches a live // object into a CONSTANT_String entry of an unsafe anonymous class. - // Method oops internally created for method handles may also + // Methods internally created for method handles may also // use pseudo-strings to link themselves to related metaobjects. bool is_pseudo_string_at(int which); diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index cef30558c90..da508131199 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -47,6 +47,7 @@ #include "logging/logMessage.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" +#include "memory/archiveUtils.hpp" #include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" @@ -898,8 +899,7 @@ bool InstanceKlass::link_class_impl(TRAPS) { // Timing // timer handles recursion - assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl"); - JavaThread* jt = (JavaThread*)THREAD; + JavaThread* jt = THREAD->as_Java_thread(); // link super class before linking this class Klass* super_klass = super(); @@ -1001,9 +1001,7 @@ bool InstanceKlass::link_class_impl(TRAPS) { #endif set_init_state(linked); if (JvmtiExport::should_post_class_prepare()) { - Thread *thread = THREAD; - assert(thread->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_prepare((JavaThread *) thread, this); + JvmtiExport::post_class_prepare(THREAD->as_Java_thread(), this); } } } @@ -1067,8 +1065,7 @@ void InstanceKlass::initialize_impl(TRAPS) { bool wait = false; - assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); - JavaThread* jt = (JavaThread*)THREAD; + JavaThread* jt = THREAD->as_Java_thread(); // refer to the JVM book page 47 for description of steps // Step 1 @@ -1444,7 +1441,7 @@ Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) { if (or_null) return NULL; ResourceMark rm(THREAD); - JavaThread *jt = (JavaThread *)THREAD; + JavaThread *jt = THREAD->as_Java_thread(); { // Atomic creation of array_klasses MutexLocker ma(THREAD, MultiArray_lock); @@ -3635,7 +3632,7 @@ void InstanceKlass::print_class_load_logging(ClassLoaderData* loader_data, Thread* THREAD = Thread::current(); Klass* caller = THREAD->is_Java_thread() - ? ((JavaThread*)THREAD)->security_get_caller_class(1) + ? THREAD->as_Java_thread()->security_get_caller_class(1) : NULL; // caller can be NULL, for example, during a JVMTI VM_Init hook if (caller != NULL) { diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index c534995c567..f955edffd69 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1329,6 +1329,7 @@ class InstanceKlass: public Klass { virtual void remove_unshareable_info(); virtual void remove_java_mirror(); void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, PackageEntry* pkg_entry, TRAPS); + void init_shared_package_entry(); // jvm support jint compute_modifier_flags(TRAPS) const; diff --git a/src/hotspot/share/oops/markWord.cpp b/src/hotspot/share/oops/markWord.cpp index 4c599f8b6ea..2c8ad2414db 100644 --- a/src/hotspot/share/oops/markWord.cpp +++ b/src/hotspot/share/oops/markWord.cpp @@ -26,6 +26,7 @@ #include "oops/markWord.hpp" #include "runtime/thread.inline.hpp" #include "runtime/objectMonitor.hpp" +#include "utilities/ostream.hpp" void markWord::print_on(outputStream* st) const { if (is_marked()) { // last bits = 11 diff --git a/src/hotspot/share/oops/markWord.hpp b/src/hotspot/share/oops/markWord.hpp index b3d97417821..2846e1ae112 100644 --- a/src/hotspot/share/oops/markWord.hpp +++ b/src/hotspot/share/oops/markWord.hpp @@ -94,6 +94,7 @@ class BasicLock; class ObjectMonitor; class JavaThread; +class outputStream; class markWord { private: diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 3b65ba17d7c..88a106fbeed 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -40,6 +40,7 @@ #include "logging/logTag.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" +#include "memory/cppVtables.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" @@ -2303,7 +2304,7 @@ bool Method::is_valid_method(const Method* m) { // Quick sanity check on pointer. return false; } else if (m->is_shared()) { - return MetaspaceShared::is_valid_shared_method(m); + return CppVtables::is_valid_shared_method(m); } else if (Metaspace::contains_non_shared(m)) { return has_method_vptr((const void*)m); } else { diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp index 7c8651439cf..9268cb789f3 100644 --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -321,7 +321,7 @@ Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { if (or_null) return NULL; ResourceMark rm; - JavaThread *jt = (JavaThread *)THREAD; + JavaThread *jt = THREAD->as_Java_thread(); { // Ensure atomic creation of higher dimensions MutexLocker mu(THREAD, MultiArray_lock); diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index db0254ab4a6..7c96f9d3dcf 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -271,9 +271,6 @@ class oopDesc { inline uint age() const; inline void incr_age(); - // mark-sweep support - void follow_body(int begin, int end); - template <typename OopClosureType> inline void oop_iterate(OopClosureType* cl); diff --git a/src/hotspot/share/oops/symbol.cpp b/src/hotspot/share/oops/symbol.cpp index b84401dbee8..bca078a7644 100644 --- a/src/hotspot/share/oops/symbol.cpp +++ b/src/hotspot/share/oops/symbol.cpp @@ -35,6 +35,7 @@ #include "memory/universe.hpp" #include "oops/symbol.hpp" #include "runtime/atomic.hpp" +#include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" #include "runtime/signature.hpp" #include "utilities/utf8.hpp" @@ -63,13 +64,14 @@ Symbol::Symbol(const u1* name, int length, int refcount) { void* Symbol::operator new(size_t sz, int len) throw() { #if INCLUDE_CDS if (DumpSharedSpaces) { - // To get deterministic output from -Xshare:dump, we ensure that Symbols are allocated in - // increasing addresses. When the symbols are copied into the archive, we preserve their - // relative address order (see SortedSymbolClosure in metaspaceShared.cpp) - // - // We cannot use arena because arena chunks are allocated by the OS. As a result, for example, - // the archived symbol of "java/lang/Object" may sometimes be lower than "java/lang/String", and - // sometimes be higher. This would cause non-deterministic contents in the archive. + MutexLocker ml(DumpRegion_lock, Mutex::_no_safepoint_check_flag); + // To get deterministic output from -Xshare:dump, we ensure that Symbols are allocated in + // increasing addresses. When the symbols are copied into the archive, we preserve their + // relative address order (sorted, see ArchiveBuilder::gather_klasses_and_symbols). + // + // We cannot use arena because arena chunks are allocated by the OS. As a result, for example, + // the archived symbol of "java/lang/Object" may sometimes be lower than "java/lang/String", and + // sometimes be higher. This would cause non-deterministic contents in the archive. DEBUG_ONLY(static void* last = 0); void* p = (void*)MetaspaceShared::symbol_space_alloc(size(len)*wordSize); assert(p > last, "must increase monotonically"); diff --git a/src/hotspot/share/oops/typeArrayKlass.cpp b/src/hotspot/share/oops/typeArrayKlass.cpp index ed95f63bde3..3c3ea730876 100644 --- a/src/hotspot/share/oops/typeArrayKlass.cpp +++ b/src/hotspot/share/oops/typeArrayKlass.cpp @@ -183,7 +183,7 @@ Klass* TypeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { if (or_null) return NULL; ResourceMark rm; - JavaThread *jt = (JavaThread *)THREAD; + JavaThread *jt = THREAD->as_Java_thread(); { // Atomic create higher dimension and link into list MutexLocker mu(THREAD, MultiArray_lock); diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 18174aed8f7..668c04f379a 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -35,21 +35,18 @@ // Defines all globals flags used by the server compiler. // -#define C2_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ - notproduct, \ - range, \ - constraint) \ - \ - diagnostic(bool, StressLCM, false, \ +#define C2_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ + \ + product(bool, StressLCM, false, DIAGNOSTIC, \ "Randomize instruction scheduling in LCM") \ \ - diagnostic(bool, StressGCM, false, \ + product(bool, StressGCM, false, DIAGNOSTIC, \ "Randomize instruction scheduling in GCM") \ \ develop(bool, StressMethodHandleLinkerInlining, false, \ @@ -116,7 +113,7 @@ "Check performance difference allowing FP " \ "associativity and commutativity...") \ \ - diagnostic_pd(bool, IdealizeClearArrayNode, \ + product_pd(bool, IdealizeClearArrayNode, DIAGNOSTIC, \ "Replace ClearArrayNode by subgraph of basic operations.") \ \ develop(bool, OptoBreakpoint, false, \ @@ -137,7 +134,7 @@ notproduct(bool, PrintOptoStatistics, false, \ "Print New compiler statistics") \ \ - diagnostic(bool, PrintOptoAssembly, false, \ + product(bool, PrintOptoAssembly, false, DIAGNOSTIC, \ "Print New compiler assembly output") \ \ develop_pd(bool, OptoPeephole, \ @@ -177,13 +174,13 @@ "Map number of unrolls for main loop via " \ "Superword Level Parallelism analysis") \ \ - experimental(bool, PostLoopMultiversioning, false, \ + product(bool, PostLoopMultiversioning, false, EXPERIMENTAL, \ "Multi versioned post loops to eliminate range checks") \ \ notproduct(bool, TraceSuperWordLoopUnrollAnalysis, false, \ "Trace what Superword Level Parallelism analysis applies") \ \ - diagnostic(bool, UseVectorMacroLogic, true, \ + product(bool, UseVectorMacroLogic, true, DIAGNOSTIC, \ "Use ternary macro logic instructions") \ \ product(intx, LoopUnrollMin, 4, \ @@ -482,11 +479,11 @@ notproduct(bool, PrintLockStatistics, false, \ "Print precise statistics on the dynamic lock usage") \ \ - diagnostic(bool, PrintPreciseBiasedLockingStatistics, false, \ + product(bool, PrintPreciseBiasedLockingStatistics, false, DIAGNOSTIC, \ "(Deprecated) Print per-lock-site statistics of biased locking " \ "in JVM") \ \ - diagnostic(bool, PrintPreciseRTMLockingStatistics, false, \ + product(bool, PrintPreciseRTMLockingStatistics, false, DIAGNOSTIC, \ "Print per-lock-site statistics of rtm locking in JVM") \ \ notproduct(bool, PrintEliminateLocks, false, \ @@ -499,7 +496,7 @@ "Sets max value cached by the java.lang.Integer autobox cache") \ range(0, max_jint) \ \ - diagnostic(bool, AggressiveUnboxing, true, \ + product(bool, AggressiveUnboxing, true, DIAGNOSTIC, \ "Control optimizations for aggressive boxing elimination") \ \ develop(bool, TracePostallocExpand, false, "Trace expanding nodes after" \ @@ -554,7 +551,7 @@ "Maximum times call Label_Root to prevent stack overflow") \ range(100, max_jint) \ \ - diagnostic(intx, DominatorSearchLimit, 1000, \ + product(intx, DominatorSearchLimit, 1000, DIAGNOSTIC, \ "Iterations limit in Node::dominates") \ range(0, max_jint) \ \ @@ -569,26 +566,26 @@ product(bool, BlockLayoutRotateLoops, true, \ "Allow back branches to be fall throughs in the block layout") \ \ - diagnostic(bool, InlineReflectionGetCallerClass, true, \ + product(bool, InlineReflectionGetCallerClass, true, DIAGNOSTIC, \ "inline sun.reflect.Reflection.getCallerClass(), known to be " \ "part of base library DLL") \ \ - diagnostic(bool, InlineObjectCopy, true, \ + product(bool, InlineObjectCopy, true, DIAGNOSTIC, \ "inline Object.clone and Arrays.copyOf[Range] intrinsics") \ \ - diagnostic(bool, SpecialStringCompareTo, true, \ + product(bool, SpecialStringCompareTo, true, DIAGNOSTIC, \ "special version of string compareTo") \ \ - diagnostic(bool, SpecialStringIndexOf, true, \ + product(bool, SpecialStringIndexOf, true, DIAGNOSTIC, \ "special version of string indexOf") \ \ - diagnostic(bool, SpecialStringEquals, true, \ + product(bool, SpecialStringEquals, true, DIAGNOSTIC, \ "special version of string equals") \ \ - diagnostic(bool, SpecialArraysEquals, true, \ + product(bool, SpecialArraysEquals, true, DIAGNOSTIC, \ "special version of Arrays.equals(char[],char[])") \ \ - diagnostic(bool, SpecialEncodeISOArray, true, \ + product(bool, SpecialEncodeISOArray, true, DIAGNOSTIC, \ "special version of ISO_8859_1$Encoder.encodeISOArray") \ \ develop(bool, BailoutToInterpreterForThrows, false, \ @@ -610,10 +607,10 @@ develop(bool, PrintDominators, false, \ "Print out dominator trees for GVN") \ \ - diagnostic(bool, TraceSpilling, false, \ + product(bool, TraceSpilling, false, DIAGNOSTIC, \ "Trace spilling") \ \ - diagnostic(bool, TraceTypeProfile, false, \ + product(bool, TraceTypeProfile, false, DIAGNOSTIC, \ "Trace type profile") \ \ develop(bool, PoisonOSREntry, true, \ @@ -629,19 +626,19 @@ "% of major receiver type to all profiled receivers") \ range(0, 100) \ \ - diagnostic(bool, PrintIntrinsics, false, \ + product(bool, PrintIntrinsics, false, DIAGNOSTIC, \ "prints attempted and successful inlining of intrinsics") \ \ develop(bool, StressReflectiveCode, false, \ "Use inexact types at allocations, etc., to test reflection") \ \ - diagnostic(bool, DebugInlinedCalls, true, \ + product(bool, DebugInlinedCalls, true, DIAGNOSTIC, \ "If false, restricts profiled locations to the root method only") \ \ notproduct(bool, VerifyLoopOptimizations, false, \ "verify major loop optimizations") \ \ - diagnostic(bool, ProfileDynamicTypes, true, \ + product(bool, ProfileDynamicTypes, true, DIAGNOSTIC, \ "do extra type profiling and use it more aggressively") \ \ develop(bool, TraceIterativeGVN, false, \ @@ -710,34 +707,34 @@ "max number of live nodes in a method") \ range(0, max_juint / 8) \ \ - diagnostic(bool, OptimizeExpensiveOps, true, \ + product(bool, OptimizeExpensiveOps, true, DIAGNOSTIC, \ "Find best control for expensive operations") \ \ - diagnostic(bool, UseMathExactIntrinsics, true, \ + product(bool, UseMathExactIntrinsics, true, DIAGNOSTIC, \ "Enables intrinsification of various java.lang.Math functions") \ \ - diagnostic(bool, UseCharacterCompareIntrinsics, false, \ + product(bool, UseCharacterCompareIntrinsics, false, DIAGNOSTIC, \ "Enables intrinsification of java.lang.Character functions") \ \ - diagnostic(bool, UseMultiplyToLenIntrinsic, false, \ + product(bool, UseMultiplyToLenIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.multiplyToLen()") \ \ - diagnostic(bool, UseSquareToLenIntrinsic, false, \ + product(bool, UseSquareToLenIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.squareToLen()") \ \ - diagnostic(bool, UseMulAddIntrinsic, false, \ + product(bool, UseMulAddIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.mulAdd()") \ \ - diagnostic(bool, UseMontgomeryMultiplyIntrinsic, false, \ + product(bool, UseMontgomeryMultiplyIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.montgomeryMultiply()") \ \ - diagnostic(bool, UseMontgomerySquareIntrinsic, false, \ + product(bool, UseMontgomerySquareIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of BigInteger.montgomerySquare()") \ \ product(bool, UseTypeSpeculation, true, \ "Speculatively propagate types from profiles") \ \ - diagnostic(bool, UseInlineDepthForSpeculativeTypes, true, \ + product(bool, UseInlineDepthForSpeculativeTypes, true, DIAGNOSTIC, \ "Carry inline depth of profile point with speculative type " \ "and give priority to profiling from lower inline depth") \ \ @@ -768,7 +765,9 @@ product(bool, UseProfiledLoopPredicate, true, \ "Move predicates out of loops based on profiling data") \ \ - diagnostic(bool, ExpandSubTypeCheckAtParseTime, false, \ - "Do not use subtype check macro node") \ + product(bool, ExpandSubTypeCheckAtParseTime, false, DIAGNOSTIC, \ + "Do not use subtype check macro node") + +// end of C2_FLAGS #endif // SHARE_OPTO_C2_GLOBALS_HPP diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index bfaada851ce..16f5a0baae5 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -54,7 +54,6 @@ class BoxLockNode; class LockNode; class UnlockNode; class JVMState; -class OopMap; class State; class StartNode; class MachCallNode; @@ -329,14 +328,12 @@ class SafePointNode : public MultiNode { // A plain safepoint advertises no memory effects (NULL): const TypePtr* adr_type = NULL) : MultiNode( edges ), - _oop_map(NULL), _jvms(jvms), _adr_type(adr_type) { init_class_id(Class_SafePoint); } - OopMap* _oop_map; // Array of OopMap info (8-bit char) for GC JVMState* const _jvms; // Pointer to list of JVM State objects const TypePtr* _adr_type; // What type of memory does this node produce? ReplacedNodes _replaced_nodes; // During parsing: list of pair of nodes from calls to GraphKit::replace_in_map() @@ -349,8 +346,6 @@ class SafePointNode : public MultiNode { void set_jvms(JVMState* s) { *(JVMState**)&_jvms = s; // override const attribute in the accessor } - OopMap *oop_map() const { return _oop_map; } - void set_oop_map(OopMap *om) { _oop_map = om; } private: void verify_input(JVMState* jvms, uint idx) const { diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index ec7ecc7bdfc..ff266916b4b 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -40,6 +40,7 @@ #include "opto/subnode.hpp" #include "opto/superword.hpp" #include "opto/vectornode.hpp" +#include "runtime/globals_extension.hpp" //------------------------------is_loop_exit----------------------------------- // Given an IfNode, return the loop-exiting projection or NULL if both diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index f901206f16a..cb1d6d69372 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -880,17 +880,14 @@ class MachCallNode : public MachSafePointNode { const TypeFunc *_tf; // Function type address _entry_point; // Address of the method being called float _cnt; // Estimate of number of times called - uint _argsize; // Size of argument block on stack const TypeFunc* tf() const { return _tf; } const address entry_point() const { return _entry_point; } const float cnt() const { return _cnt; } - uint argsize() const { return _argsize; } void set_tf(const TypeFunc* tf) { _tf = tf; } void set_entry_point(address p) { _entry_point = p; } void set_cnt(float c) { _cnt = c; } - void set_argsize(int s) { _argsize = s; } MachCallNode() : MachSafePointNode() { init_class_id(Class_MachCall); diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 2bbd5a28c8e..b07b4e03be9 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -1305,10 +1305,6 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { if (OptoReg::is_valid(reg2)) rm->Insert( reg2 ); } // End of for all arguments - - // Compute number of stack slots needed to restore stack in case of - // Pascal-style argument popping. - mcall->_argsize = out_arg_limit_per_call - begin_out_arg_area; } // Compute the max stack slot killed by any call. These will not be @@ -1346,9 +1342,6 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { assert((mcall == NULL) || (mcall->jvms() == NULL) || (mcall->jvms()->debug_start() + mcall->_jvmadj == mcall->tf()->domain()->cnt()), ""); - // Move the OopMap - msfpt->_oop_map = sfpt->_oop_map; - // Add additional edges. if (msfpt->mach_constant_base_node_input() != (uint)-1 && !msfpt->is_MachCallLeaf()) { // For these calls we can not add MachConstantBase in expand(), as the diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index c55b6d2b8da..c211557eacb 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -358,9 +358,6 @@ class Matcher : public PhaseTransform { // These calls are all generated by the ADLC - // TRUE - grows up, FALSE - grows down (Intel) - virtual bool stack_direction() const; - // Java-Java calling convention // (what you use when Java calls Java) @@ -418,12 +415,12 @@ class Matcher : public PhaseTransform { // The Method-klass-holder may be passed in the inline_cache_reg // and then expanded into the inline_cache_reg and a method_ptr register - static OptoReg::Name interpreter_method_oop_reg(); - static int interpreter_method_oop_reg_encode(); + static OptoReg::Name interpreter_method_reg(); + static int interpreter_method_reg_encode(); - static OptoReg::Name compiler_method_oop_reg(); - static const RegMask &compiler_method_oop_reg_mask(); - static int compiler_method_oop_reg_encode(); + static OptoReg::Name compiler_method_reg(); + static const RegMask &compiler_method_reg_mask(); + static int compiler_method_reg_encode(); // Interpreter's Frame Pointer Register static OptoReg::Name interpreter_frame_pointer_reg(); @@ -440,9 +437,6 @@ class Matcher : public PhaseTransform { OptoReg::Name c_frame_pointer() const; static RegMask c_frame_ptr_mask; - // !!!!! Special stuff for building ScopeDescs - virtual int regnum_to_fpu_offset(int regnum); - // Is this branch offset small enough to be addressed by a short branch? bool is_short_branch_offset(int rule, int br_size, int offset); diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 3f41a2ff7fa..dc7af3d4b29 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -250,7 +250,7 @@ const Type* Type::make_from_constant(ciConstant constant, bool require_constant, guarantee(require_constant || oop_constant->should_be_constant(), "con_type must get computed"); con_type = TypeOopPtr::make_from_constant(oop_constant, require_constant); if (Compile::current()->eliminate_boxing() && is_autobox_cache) { - con_type = con_type->is_aryptr()->cast_to_autobox_cache(true); + con_type = con_type->is_aryptr()->cast_to_autobox_cache(); } if (stable_dimension > 0) { assert(FoldStableValues, "sanity"); @@ -4203,15 +4203,14 @@ int TypeAryPtr::stable_dimension() const { } //----------------------cast_to_autobox_cache----------------------------------- -const TypeAryPtr* TypeAryPtr::cast_to_autobox_cache(bool cache) const { - if (is_autobox_cache() == cache) return this; +const TypeAryPtr* TypeAryPtr::cast_to_autobox_cache() const { + if (is_autobox_cache()) return this; const TypeOopPtr* etype = elem()->make_oopptr(); if (etype == NULL) return this; // The pointers in the autobox arrays are always non-null. - TypePtr::PTR ptr_type = cache ? TypePtr::NotNull : TypePtr::AnyNull; etype = etype->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr(); const TypeAry* new_ary = TypeAry::make(etype, size(), is_stable()); - return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth, cache); + return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth, /*is_autobox_cache=*/true); } //------------------------------eq--------------------------------------------- diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 08053369b09..989630b17a8 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -1226,7 +1226,7 @@ class TypeAryPtr : public TypeOopPtr { const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const; int stable_dimension() const; - const TypeAryPtr* cast_to_autobox_cache(bool cache) const; + const TypeAryPtr* cast_to_autobox_cache() const; static jint max_array_length(BasicType etype) ; diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index aabed4ecb3a..f0f779e3a87 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -329,7 +329,7 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR // check whether the current caller thread holds the lock or not. // If not, increment the corresponding counter if (ObjectSynchronizer:: - query_lock_ownership((JavaThread*)THREAD, class_loader) != + query_lock_ownership(thread, class_loader) != ObjectSynchronizer::owner_self) { ClassLoader::sync_JNIDefineClassLockFreeCounter()->inc(); } @@ -3940,7 +3940,7 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae // If executing from an atexit hook we may be in the VMThread. if (t->is_Java_thread()) { // If the thread has been attached this operation is a no-op - *(JNIEnv**)penv = ((JavaThread*) t)->jni_environment(); + *(JNIEnv**)penv = t->as_Java_thread()->jni_environment(); return JNI_OK; } else { return JNI_ERR; @@ -4078,7 +4078,7 @@ jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { VM_Exit::block_if_vm_exited(); - JavaThread* thread = (JavaThread*) current; + JavaThread* thread = current->as_Java_thread(); if (thread->has_last_Java_frame()) { HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR); // Can't detach a thread that's running java, that can't work. @@ -4133,7 +4133,7 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { Thread* thread = Thread::current_or_null(); if (thread != NULL && thread->is_Java_thread()) { if (Threads::is_supported_jni_version_including_1_1(version)) { - *(JNIEnv**)penv = ((JavaThread*) thread)->jni_environment(); + *(JNIEnv**)penv = thread->as_Java_thread()->jni_environment(); ret = JNI_OK; return ret; diff --git a/src/hotspot/share/prims/jniCheck.cpp b/src/hotspot/share/prims/jniCheck.cpp index 47da2257a83..fd9e2e3bab7 100644 --- a/src/hotspot/share/prims/jniCheck.cpp +++ b/src/hotspot/share/prims/jniCheck.cpp @@ -93,11 +93,12 @@ static struct JNINativeInterface_ * unchecked_jni_NativeInterface; #define JNI_ENTRY_CHECKED(result_type, header) \ extern "C" { \ result_type JNICALL header { \ - JavaThread* thr = (JavaThread*) Thread::current_or_null(); \ - if (thr == NULL || !thr->is_Java_thread()) { \ + Thread* cur = Thread::current_or_null(); \ + if (cur == NULL || !cur->is_Java_thread()) { \ tty->print_cr("%s", fatal_using_jnienv_in_nonjava); \ os::abort(true); \ } \ + JavaThread* thr = cur->as_Java_thread(); \ JNIEnv* xenv = thr->jni_environment(); \ if (env != xenv) { \ NativeReportJNIFatalError(thr, warn_wrong_jnienv); \ diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 0b415808715..e6313ba37f2 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -65,6 +65,7 @@ #include "prims/stackwalk.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.inline.hpp" @@ -142,7 +143,7 @@ static void trace_class_resolution_impl(Klass* to_class, TRAPS) { const char * source_file = NULL; const char * trace = "explicit"; InstanceKlass* caller = NULL; - JavaThread* jthread = (JavaThread*) THREAD; + JavaThread* jthread = THREAD->as_Java_thread(); if (jthread->has_last_Java_frame()) { vframeStream vfst(jthread); @@ -611,8 +612,7 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod jint skip_frames, jint frame_count, jint start_index, jobjectArray frames)) JVMWrapper("JVM_CallStackWalk"); - JavaThread* jt = (JavaThread*) THREAD; - if (!jt->is_Java_thread() || !jt->has_last_Java_frame()) { + if (!thread->has_last_Java_frame()) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: no stack trace", NULL); } @@ -671,7 +671,7 @@ JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)) Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); JavaThreadInObjectWaitState jtiows(thread, ms != 0); if (JvmtiExport::should_post_monitor_wait()) { - JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms); + JvmtiExport::post_monitor_wait(thread, (oop)obj(), ms); // The current thread already owns the monitor and it has not yet // been added to the wait queue so the current thread cannot be @@ -921,7 +921,7 @@ static void is_lock_held_by_thread(Handle loader, PerfCounter* counter, TRAPS) { // check whether the current caller thread holds the lock or not. // If not, increment the corresponding counter - if (ObjectSynchronizer::query_lock_ownership((JavaThread*)THREAD, loader) != + if (ObjectSynchronizer::query_lock_ownership(THREAD->as_Java_thread(), loader) != ObjectSynchronizer::owner_self) { counter->inc(); } @@ -934,8 +934,7 @@ static jclass jvm_define_class_common(const char *name, TRAPS) { if (source == NULL) source = "__JVM_DefineClass__"; - assert(THREAD->is_Java_thread(), "must be a JavaThread"); - JavaThread* jt = (JavaThread*) THREAD; + JavaThread* jt = THREAD->as_Java_thread(); PerfClassTraceTime vmtimer(ClassLoader::perf_define_appclass_time(), ClassLoader::perf_define_appclass_selftime(), @@ -989,7 +988,6 @@ enum { static jclass jvm_lookup_define_class(jclass lookup, const char *name, const jbyte *buf, jsize len, jobject pd, jboolean init, int flags, jobject classData, TRAPS) { - assert(THREAD->is_Java_thread(), "must be a JavaThread"); ResourceMark rm(THREAD); Klass* lookup_k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(lookup)); @@ -1230,6 +1228,11 @@ JVM_ENTRY (void, JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject so Modules::add_reads_module(from_module, source_module, CHECK); JVM_END +JVM_ENTRY(void, JVM_DefineArchivedModules(JNIEnv *env, jobject platform_loader, jobject system_loader)) + JVMWrapper("JVM_DefineArchivedModules"); + Modules::define_archived_modules(platform_loader, system_loader, CHECK); +JVM_END + // Reflection support ////////////////////////////////////////////////////////////////////////////// JVM_ENTRY(jstring, JVM_InitClassName(JNIEnv *env, jclass cls)) @@ -3310,12 +3313,11 @@ JVM_END JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj)) JVMWrapper("JVM_HoldsLock"); - assert(THREAD->is_Java_thread(), "sanity check"); if (obj == NULL) { THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); } Handle h_obj(THREAD, JNIHandles::resolve(obj)); - return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj); + return ObjectSynchronizer::current_thread_holds_lock(thread, h_obj); JVM_END @@ -3726,7 +3728,7 @@ JVM_ENTRY(void, JVM_InitializeFromArchive(JNIEnv* env, jclass cls)) JVMWrapper("JVM_InitializeFromArchive"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); assert(k->is_klass(), "just checking"); - HeapShared::initialize_from_archived_subgraph(k); + HeapShared::initialize_from_archived_subgraph(k, THREAD); JVM_END JVM_ENTRY(void, JVM_RegisterLambdaProxyClassForArchiving(JNIEnv* env, diff --git a/src/hotspot/share/prims/jvmtiEnter.xsl b/src/hotspot/share/prims/jvmtiEnter.xsl index 023b759c850..2ed29d5cb6f 100644 --- a/src/hotspot/share/prims/jvmtiEnter.xsl +++ b/src/hotspot/share/prims/jvmtiEnter.xsl @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0"?> <!-- Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -20,7 +20,7 @@ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA or visit www.oracle.com if you need additional information or have any questions. - + --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> @@ -63,7 +63,7 @@ // Error names const char* JvmtiUtil::_error_names[] = { </xsl:text> - <xsl:call-template name="fillEntityName"> + <xsl:call-template name="fillEntityName"> <xsl:with-param name="entities" select="errorsection/errorcategory/errorid"/> </xsl:call-template> <xsl:text> @@ -73,7 +73,7 @@ const char* JvmtiUtil::_error_names[] = { // Event threaded const bool JvmtiUtil::_event_threaded[] = { </xsl:text> - <xsl:call-template name="fillEventThreaded"> + <xsl:call-template name="fillEventThreaded"> <xsl:with-param name="entities" select="eventsection/event"/> </xsl:call-template> <xsl:text> @@ -92,7 +92,7 @@ const bool JvmtiUtil::_event_threaded[] = { <xsl:if test="count(../../eventsection/event[@num > $mynum]) = 0"> <xsl:value-of select="@num"/> </xsl:if> - </xsl:for-each> + </xsl:for-each> </xsl:variable> <xsl:text>jbyte JvmtiTrace::_event_trace_flags[</xsl:text> @@ -106,7 +106,7 @@ jint JvmtiTrace::_max_event_index = </xsl:text> // Event names const char* JvmtiTrace::_event_names[] = { </xsl:text> - <xsl:call-template name="fillEntityName"> + <xsl:call-template name="fillEntityName"> <xsl:with-param name="entities" select="eventsection/event"/> </xsl:call-template> <xsl:text> @@ -203,7 +203,7 @@ const bool JvmtiUtil::has_event_capability(jvmtiEvent event_type, const jvmtiCap <xsl:if test="count(../../category/function[@num > $mynum]) = 0"> <xsl:value-of select="@num"/> </xsl:if> - </xsl:for-each> + </xsl:for-each> </xsl:variable> <xsl:text>jbyte JvmtiTrace::_trace_flags[</xsl:text> @@ -248,7 +248,7 @@ struct jvmtiInterface_1_ jvmti</xsl:text> <xsl:value-of select="$trace"/> <xsl:text>_Interface = { </xsl:text> - + <xsl:call-template name="fillFuncStruct"> <xsl:with-param name="funcs" select="category/function[count(@hide)=0]"/> </xsl:call-template> @@ -281,7 +281,7 @@ struct jvmtiInterface_1_ jvmti</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text> RESERVED */ - NULL</xsl:text> + NULL</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -314,7 +314,7 @@ struct jvmtiInterface_1_ jvmti</xsl:text> <xsl:text>"</xsl:text> </xsl:when> <xsl:otherwise> - <xsl:text> NULL</xsl:text> + <xsl:text> NULL</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -347,12 +347,12 @@ struct jvmtiInterface_1_ jvmti</xsl:text> <xsl:text> false</xsl:text> </xsl:when> <xsl:otherwise> - <xsl:text> true</xsl:text> + <xsl:text> true</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> - <xsl:text> false</xsl:text> + <xsl:text> false</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -387,7 +387,7 @@ struct jvmtiInterface_1_ jvmti</xsl:text> <xsl:text> // // </xsl:text><xsl:value-of select="@label"/><xsl:text> functions - // + // </xsl:text> <xsl:apply-templates select="function[count(@hide)=0]"/> </xsl:template> @@ -398,23 +398,23 @@ struct jvmtiInterface_1_ jvmti</xsl:text> </xsl:text> </xsl:param> <xsl:value-of select="$space"/> - - <xsl:choose> + + <xsl:choose> <xsl:when test="count(@callbacksafe)=0 or not(contains(@callbacksafe,'safe'))"> - <xsl:text>if (this_thread == NULL || !this_thread->is_Java_thread()) {</xsl:text> - </xsl:when> - <xsl:otherwise> + <xsl:text>if (this_thread == NULL || !this_thread->is_Java_thread()) {</xsl:text> + </xsl:when> + <xsl:otherwise> <xsl:choose> <xsl:when test="count(@phase)=0 or contains(@phase,'live') or contains(@phase,'start')"> <xsl:text>if (this_thread == NULL || (!this_thread->is_Java_thread() && !this_thread->is_Named_thread())) {</xsl:text> </xsl:when> <xsl:otherwise> - <xsl:text>if (!this_thread->is_Java_thread()) {</xsl:text> + <xsl:text>if (!this_thread->is_Java_thread()) {</xsl:text> </xsl:otherwise> </xsl:choose> - </xsl:otherwise> - </xsl:choose> - + </xsl:otherwise> + </xsl:choose> + <xsl:if test="$trace='Trace'"> <xsl:value-of select="$space"/> <xsl:text> if (trace_flags) {</xsl:text> @@ -428,10 +428,10 @@ struct jvmtiInterface_1_ jvmti</xsl:text> <xsl:value-of select="$space"/> <xsl:text> return JVMTI_ERROR_UNATTACHED_THREAD;</xsl:text> <xsl:value-of select="$space"/> - <xsl:text>}</xsl:text> - <xsl:value-of select="$space"/> + <xsl:text>}</xsl:text> + <xsl:value-of select="$space"/> <xsl:if test="count(@impl)=0 or not(contains(@impl,'innative'))"> - <xsl:text>JavaThread* current_thread = (JavaThread*)this_thread;</xsl:text> + <xsl:text>JavaThread* current_thread = this_thread->as_Java_thread();</xsl:text> <xsl:value-of select="$space"/> <xsl:text>ThreadInVMfromNative __tiv(current_thread);</xsl:text> <xsl:value-of select="$space"/> @@ -456,7 +456,7 @@ struct jvmtiInterface_1_ jvmti</xsl:text> </xsl:text> <xsl:if test="$trace='Trace'"> <xsl:text> if (trace_flags) { - log_trace(jvmti)("[%s] %s %s", curr_thread_name, func_name, + log_trace(jvmti)("[%s] %s %s", curr_thread_name, func_name, JvmtiUtil::error_name(JVMTI_ERROR_MUST_POSSESS_CAPABILITY)); } </xsl:text> @@ -496,9 +496,9 @@ static jvmtiError JNICALL </xsl:text> </xsl:if> <xsl:text> return JVMTI_ERROR_WRONG_PHASE; - }</xsl:text> + }</xsl:text> - <xsl:text> + <xsl:text> Thread* this_thread = Thread::current_or_null(); </xsl:text> <xsl:apply-templates select="." mode="transition"/> @@ -513,7 +513,7 @@ static jvmtiError JNICALL </xsl:text> <xsl:if test="$trace='Trace'"> <xsl:text> if (trace_flags) { - log_trace(jvmti)("[-] %s %s", func_name, + log_trace(jvmti)("[-] %s %s", func_name, JvmtiUtil::error_name(JVMTI_ERROR_WRONG_PHASE)); } </xsl:text> @@ -526,7 +526,7 @@ static jvmtiError JNICALL </xsl:text> <xsl:if test="$trace='Trace'"> <xsl:text> if (trace_flags) { - log_trace(jvmti)("[-] %s %s", func_name, + log_trace(jvmti)("[-] %s %s", func_name, JvmtiUtil::error_name(JVMTI_ERROR_WRONG_PHASE)); } </xsl:text> @@ -545,7 +545,7 @@ static jvmtiError JNICALL </xsl:text> <xsl:if test="$trace='Trace'"> <xsl:text> if (trace_flags) { - log_trace(jvmti)("[%s] %s %s env=" PTR_FORMAT, curr_thread_name, func_name, + log_trace(jvmti)("[%s] %s %s env=" PTR_FORMAT, curr_thread_name, func_name, JvmtiUtil::error_name(JVMTI_ERROR_INVALID_ENVIRONMENT), p2i(env)); } </xsl:text> @@ -555,11 +555,11 @@ static jvmtiError JNICALL </xsl:text> <xsl:apply-templates select="capabilities/required"/> - + <xsl:text> jvmtiError err; </xsl:text> <xsl:choose> - <xsl:when test="count(@phase)=1 and not(contains(@phase,'live')) and not(contains(@phase,'start'))"> + <xsl:when test="count(@phase)=1 and not(contains(@phase,'live')) and not(contains(@phase,'start'))"> <xsl:choose> <xsl:when test="count(@callbacksafe)=0 or not(contains(@callbacksafe,'safe'))"> <xsl:text> if (Threads::number_of_threads() != 0) { @@ -589,16 +589,16 @@ static jvmtiError JNICALL </xsl:apply-templates> <xsl:text> </xsl:text> - <xsl:apply-templates select="." mode="doCall"/> + <xsl:apply-templates select="." mode="doCall"/> <xsl:text> } else { </xsl:text> <!-- we are pre-thread - no thread transition code --> - <xsl:apply-templates select="." mode="doCall"/> + <xsl:apply-templates select="." mode="doCall"/> <xsl:text> } </xsl:text> </xsl:when> <xsl:otherwise> - <xsl:apply-templates select="." mode="doCall"/> + <xsl:apply-templates select="." mode="doCall"/> </xsl:otherwise> </xsl:choose> <xsl:text> return err; @@ -613,7 +613,7 @@ static jvmtiError JNICALL <xsl:template match="function" mode="doCall"> <xsl:apply-templates select="parameters" mode="dochecks"/> - <xsl:apply-templates select="." mode="traceBefore"/> + <xsl:apply-templates select="." mode="traceBefore"/> <xsl:apply-templates select="." mode="genCall"/> <xsl:apply-templates select="." mode="traceAfter"/> </xsl:template> @@ -674,7 +674,7 @@ static jvmtiError JNICALL log_error(jvmti)("[%s] %s } %s - erroneous arg is </xsl:text> <xsl:value-of select="@id"/> <xsl:value-of select="$comment"/> - <xsl:text>", curr_thread_name, func_name, + <xsl:text>", curr_thread_name, func_name, JvmtiUtil::error_name(</xsl:text> <xsl:value-of select="$err"/> <xsl:text>)</xsl:text> @@ -696,7 +696,7 @@ static jvmtiError JNICALL </xsl:text> <xsl:apply-templates select="." mode="traceIn"/> <xsl:text> } - log_error(jvmti)("[%s] %s } %s", curr_thread_name, func_name, + log_error(jvmti)("[%s] %s } %s", curr_thread_name, func_name, JvmtiUtil::error_name(err)); } else if ((trace_flags & JvmtiTrace::SHOW_OUT) != 0) { log_trace(jvmti)("[%s] %s }", curr_thread_name, func_name); @@ -709,11 +709,11 @@ static jvmtiError JNICALL <xsl:param name="endParam"></xsl:param> <xsl:text> log_trace(jvmti)("[%s] %s { </xsl:text> <xsl:apply-templates select="parameters" mode="traceInFormat"> - <xsl:with-param name="endParam" select="$endParam"/> + <xsl:with-param name="endParam" select="$endParam"/> </xsl:apply-templates> <xsl:text>", curr_thread_name, func_name</xsl:text> <xsl:apply-templates select="parameters" mode="traceInValue"> - <xsl:with-param name="endParam" select="$endParam"/> + <xsl:with-param name="endParam" select="$endParam"/> </xsl:apply-templates> <xsl:text>); </xsl:text> @@ -736,7 +736,7 @@ static jvmtiError JNICALL <xsl:value-of select="$name"/> <xsl:text> == NULL) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_NULL_POINTER</xsl:with-param> </xsl:apply-templates> <xsl:text> @@ -752,7 +752,7 @@ static jvmtiError JNICALL <xsl:text>; if (rmonitor == NULL) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_MONITOR</xsl:with-param> <xsl:with-param name="comment"> - raw monitor is NULL</xsl:with-param> </xsl:apply-templates> @@ -760,7 +760,7 @@ static jvmtiError JNICALL } if (!rmonitor->is_valid()) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_MONITOR</xsl:with-param> <xsl:with-param name="comment"> - not a raw monitor " PTR_FORMAT "</xsl:with-param> <xsl:with-param name="extraValue">, p2i(rmonitor)</xsl:with-param> @@ -777,7 +777,7 @@ static jvmtiError JNICALL <xsl:text>, &java_thread, NULL); if (err != JVMTI_ERROR_NONE) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">err</xsl:with-param> <xsl:with-param name="comment"> - jthread did not convert to a JavaThread - jthread = " PTR_FORMAT "</xsl:with-param> <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param> @@ -822,7 +822,7 @@ static jvmtiError JNICALL <xsl:text> if (depth < 0) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_ILLEGAL_ARGUMENT</xsl:with-param> <xsl:with-param name="comment"> - negative depth - jthread = " INT32_FORMAT "</xsl:with-param> <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param> @@ -836,12 +836,12 @@ static jvmtiError JNICALL <xsl:param name="name"/> <!-- for JVMTI a jclass/jmethodID becomes just jmethodID --> <xsl:if test="count(@method)=0"> - <xsl:text> oop k_mirror = JNIHandles::resolve_external_guard(</xsl:text> + <xsl:text> oop k_mirror = JNIHandles::resolve_external_guard(</xsl:text> <xsl:value-of select="$name"/> <xsl:text>); if (k_mirror == NULL) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_CLASS</xsl:with-param> <xsl:with-param name="comment"> - resolved to NULL - jclass = " PTR_FORMAT "</xsl:with-param> <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param> @@ -850,7 +850,7 @@ static jvmtiError JNICALL } if (!k_mirror->is_a(SystemDictionary::Class_klass())) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_CLASS</xsl:with-param> <xsl:with-param name="comment"> - not a class - jclass = " PTR_FORMAT "</xsl:with-param> <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param> @@ -862,7 +862,7 @@ static jvmtiError JNICALL <xsl:text> if (java_lang_Class::is_primitive(k_mirror)) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_CLASS</xsl:with-param> <xsl:with-param name="comment"> - is a primitive class - jclass = " PTR_FORMAT "</xsl:with-param> <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param> @@ -872,7 +872,7 @@ static jvmtiError JNICALL Klass* k_oop = java_lang_Class::as_Klass(k_mirror); if (k_oop == NULL) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_CLASS</xsl:with-param> <xsl:with-param name="comment"> - no Klass* - jclass = " PTR_FORMAT "</xsl:with-param> <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param> @@ -891,7 +891,7 @@ static jvmtiError JNICALL <xsl:value-of select="$name"/> <xsl:text>);
</xsl:text> <xsl:text> if (checked_method == NULL) {
</xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_METHODID</xsl:with-param> <xsl:with-param name="comment"></xsl:with-param> <xsl:with-param name="extraValue"></xsl:with-param> @@ -899,9 +899,9 @@ static jvmtiError JNICALL <xsl:text>
</xsl:text> <xsl:text> }
</xsl:text> <xsl:if test="count(@native)=1 and contains(@native,'error')"> - <xsl:text> if (checked_method->is_native()) {
</xsl:text> - <xsl:text> return JVMTI_ERROR_NATIVE_METHOD;
</xsl:text> - <xsl:text> }
</xsl:text> + <xsl:text> if (checked_method->is_native()) {
</xsl:text> + <xsl:text> return JVMTI_ERROR_NATIVE_METHOD;
</xsl:text> + <xsl:text> }
</xsl:text> </xsl:if> </xsl:template> @@ -913,7 +913,7 @@ static jvmtiError JNICALL <xsl:text> if (!JvmtiEnv::get_field_descriptor(k_oop, </xsl:text> <xsl:value-of select="$name"/> <xsl:text>, &fdesc)) {
</xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_FIELDID</xsl:with-param> </xsl:apply-templates> <xsl:text>
</xsl:text> @@ -930,7 +930,7 @@ static jvmtiError JNICALL <xsl:value-of select="@min"/> <xsl:text>) { </xsl:text> - <xsl:apply-templates select=".." mode="traceError"> + <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_ILLEGAL_ARGUMENT</xsl:with-param> </xsl:apply-templates> <xsl:text> @@ -1050,7 +1050,7 @@ static jvmtiError JNICALL <xsl:text>=" PTR_FORMAT "</xsl:text> </xsl:when> <xsl:otherwise> - <xsl:apply-templates select="$child" mode="traceInFormat"/> + <xsl:apply-templates select="$child" mode="traceInFormat"/> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -1066,7 +1066,7 @@ static jvmtiError JNICALL <xsl:otherwise> <xsl:apply-templates select="$child" mode="traceInValue"/> </xsl:otherwise> - </xsl:choose> + </xsl:choose> </xsl:template> <xsl:template match="inptr" mode="traceInFormat"> @@ -1118,8 +1118,8 @@ static jvmtiError JNICALL <xsl:param name="name"/> <!-- If we convert and test threads --> <xsl:if test="count(@impl)=0 or not(contains(@impl,'noconvert'))"> - <xsl:text>, - JvmtiTrace::safe_get_thread_name(java_thread)</xsl:text> + <xsl:text>, + JvmtiTrace::safe_get_thread_name(java_thread)</xsl:text> </xsl:if> </xsl:template> @@ -1137,7 +1137,7 @@ static jvmtiError JNICALL <xsl:template match="jclass" mode="traceInValue"> <!-- for JVMTI a jclass/jmethodID becomes just jmethodID --> <xsl:if test="count(@method)=0"> - <xsl:text>, + <xsl:text>, JvmtiTrace::get_class_name(k_mirror)</xsl:text> </xsl:if> </xsl:template> @@ -1151,7 +1151,7 @@ static jvmtiError JNICALL <xsl:template match="jmethodID" mode="traceInValue"> <xsl:param name="name"/> - <xsl:text>, + <xsl:text>, checked_method == NULL? "NULL" : checked_method->klass_name()->as_C_string(), checked_method == NULL? "NULL" : checked_method->name()->as_C_string() </xsl:text> @@ -1173,7 +1173,7 @@ static jvmtiError JNICALL <xsl:param name="name"/> <xsl:text>, </xsl:text> <xsl:value-of select="$name"/> - <xsl:text>, + <xsl:text>, </xsl:text> <xsl:choose> <xsl:when test=".='jvmtiError'"> diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index a2b90d1c271..d50f903c7df 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -3308,7 +3308,7 @@ JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) { } else { Thread* thread = Thread::current(); if (thread->is_Java_thread()) { - JavaThread* current_thread = (JavaThread*)thread; + JavaThread* current_thread = thread->as_Java_thread(); /* Transition to thread_blocked without entering vm state */ /* This is really evil. Normally you can't undo _thread_blocked */ diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 513acfe68bf..21acadd8a71 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -663,13 +663,13 @@ JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThre mon = java_thread->current_pending_monitor(); if (mon != NULL) { // The thread is trying to enter() an ObjectMonitor. - obj = (oop)mon->object(); + obj = mon->object(); assert(obj != NULL, "ObjectMonitor should have a valid object!"); } // implied else: no contended ObjectMonitor } else { // thread is doing an Object.wait() call - obj = (oop)mon->object(); + obj = mon->object(); assert(obj != NULL, "Object.wait() should have an object"); } @@ -741,7 +741,7 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread // Save object of current wait() call (if any) for later comparison. ObjectMonitor *mon = java_thread->current_waiting_monitor(); if (mon != NULL) { - wait_obj = (oop)mon->object(); + wait_obj = mon->object(); } } oop pending_obj = NULL; @@ -752,7 +752,7 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread // Save object of current enter() call (if any) for later comparison. ObjectMonitor *mon = java_thread->current_pending_monitor(); if (mon != NULL) { - pending_obj = (oop)mon->object(); + pending_obj = mon->object(); } } @@ -1077,7 +1077,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec } Thread *t = mon->thread_of_waiter(waiter); if (t != NULL && t->is_Java_thread()) { - JavaThread *wjava_thread = (JavaThread *)t; + JavaThread *wjava_thread = t->as_Java_thread(); // If the thread was found on the ObjectWaiter list, then // it has not been notified. This thread can't change the // state of the monitor so it doesn't need to be suspended. @@ -1268,8 +1268,7 @@ VM_GetThreadListStackTraces::doit() { void GetSingleStackTraceClosure::do_thread(Thread *target) { - assert(target->is_Java_thread(), "just checking"); - JavaThread *jt = (JavaThread *)target; + JavaThread *jt = target->as_Java_thread(); oop thread_oop = jt->threadObj(); if (!jt->is_exiting() && thread_oop != NULL) { @@ -1435,7 +1434,7 @@ JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) { } if (mon->owner() == _java_thread ) { // Filter out on stack monitors collected during stack walk. - oop obj = (oop)mon->object(); + oop obj = mon->object(); bool found = false; for (int j = 0; j < _owned_monitors_list->length(); j++) { jobject jobj = ((jvmtiMonitorStackDepthInfo*)_owned_monitors_list->at(j))->monitor; @@ -1526,8 +1525,7 @@ SetFramePopClosure::do_thread(Thread *target) { void GetOwnedMonitorInfoClosure::do_thread(Thread *target) { - assert(target->is_Java_thread(), "just checking"); - JavaThread *jt = (JavaThread *)target; + JavaThread *jt = target->as_Java_thread(); if (!jt->is_exiting() && (jt->threadObj() != NULL)) { _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, jt, @@ -1537,8 +1535,7 @@ GetOwnedMonitorInfoClosure::do_thread(Thread *target) { void GetCurrentContendedMonitorClosure::do_thread(Thread *target) { - assert(target->is_Java_thread(), "just checking"); - JavaThread *jt = (JavaThread *)target; + JavaThread *jt = target->as_Java_thread(); if (!jt->is_exiting() && (jt->threadObj() != NULL)) { _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread, jt, @@ -1548,8 +1545,7 @@ GetCurrentContendedMonitorClosure::do_thread(Thread *target) { void GetStackTraceClosure::do_thread(Thread *target) { - assert(target->is_Java_thread(), "just checking"); - JavaThread *jt = (JavaThread *)target; + JavaThread *jt = target->as_Java_thread(); if (!jt->is_exiting() && jt->threadObj() != NULL) { _result = ((JvmtiEnvBase *)_env)->get_stack_trace(jt, _start_depth, _max_count, @@ -1568,8 +1564,7 @@ GetFrameCountClosure::do_thread(Thread *target) { void GetFrameLocationClosure::do_thread(Thread *target) { - assert(target->is_Java_thread(), "just checking"); - JavaThread *jt = (JavaThread *)target; + JavaThread *jt = target->as_Java_thread(); if (!jt->is_exiting() && jt->threadObj() != NULL) { _result = ((JvmtiEnvBase*)_env)->get_frame_location(jt, _depth, _method_ptr, _location_ptr); diff --git a/src/hotspot/share/prims/jvmtiEnvThreadState.cpp b/src/hotspot/share/prims/jvmtiEnvThreadState.cpp index e58f2031dab..c6ed99e4a67 100644 --- a/src/hotspot/share/prims/jvmtiEnvThreadState.cpp +++ b/src/hotspot/share/prims/jvmtiEnvThreadState.cpp @@ -255,7 +255,7 @@ class GetCurrentLocationClosure : public HandshakeClosure { _method_id(NULL), _bci(0) {} void do_thread(Thread *target) { - JavaThread *jt = (JavaThread *)target; + JavaThread *jt = target->as_Java_thread(); ResourceMark rmark; // jt != Thread::current() RegisterMap rm(jt, false); // There can be a race condition between a VM_Operation reaching a safepoint diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp b/src/hotspot/share/prims/jvmtiEventController.cpp index 586f0f277fe..5d6b49b22aa 100644 --- a/src/hotspot/share/prims/jvmtiEventController.cpp +++ b/src/hotspot/share/prims/jvmtiEventController.cpp @@ -198,7 +198,7 @@ class EnterInterpOnlyModeClosure : public HandshakeClosure { public: EnterInterpOnlyModeClosure() : HandshakeClosure("EnterInterpOnlyMode") { } void do_thread(Thread* th) { - JavaThread* jt = (JavaThread*) th; + JavaThread* jt = th->as_Java_thread(); JvmtiThreadState* state = jt->jvmti_thread_state(); // Set up the current stack depth for later tracking @@ -331,8 +331,7 @@ void JvmtiEventControllerPrivate::enter_interp_only_mode(JvmtiThreadState *state EC_TRACE(("[%s] # Entering interpreter only mode", JvmtiTrace::safe_get_thread_name(state->get_thread()))); EnterInterpOnlyModeClosure hs; - assert(state->get_thread()->is_Java_thread(), "just checking"); - JavaThread *target = (JavaThread *)state->get_thread(); + JavaThread *target = state->get_thread(); Thread *current = Thread::current(); if (target == current || target->active_handshaker() == current) { hs.do_thread(target); @@ -645,7 +644,6 @@ JvmtiEventControllerPrivate::recompute_enabled() { void JvmtiEventControllerPrivate::thread_started(JavaThread *thread) { - assert(thread->is_Java_thread(), "Must be JavaThread"); assert(thread == Thread::current(), "must be current thread"); assert(JvmtiEnvBase::environments_might_exist(), "to enter event controller, JVM TI environments must exist"); diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index d97ade70d2d..bfe5d574a7c 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -108,7 +108,7 @@ class JvmtiThreadEventTransition : StackObj { public: JvmtiThreadEventTransition(Thread *thread) : _rm(), _hm(thread) { if (thread->is_Java_thread()) { - _jthread = (JavaThread *)thread; + _jthread = thread->as_Java_thread(); _saved_state = _jthread->thread_state(); if (_saved_state == _thread_in_Java) { ThreadStateTransition::transition_from_java(_jthread, _thread_in_native); @@ -2306,7 +2306,7 @@ void JvmtiExport::record_vm_internal_object_allocation(oop obj) { NoSafepointVerifier no_sfpt; // Cannot take safepoint here so do not use state_for to get // jvmti thread state. - JvmtiThreadState *state = ((JavaThread*)thread)->jvmti_thread_state(); + JvmtiThreadState *state = thread->as_Java_thread()->jvmti_thread_state(); if (state != NULL) { // state is non NULL when VMObjectAllocEventCollector is enabled. JvmtiVMObjectAllocEventCollector *collector; @@ -2330,7 +2330,7 @@ void JvmtiExport::record_sampled_internal_object_allocation(oop obj) { NoSafepointVerifier no_sfpt; // Cannot take safepoint here so do not use state_for to get // jvmti thread state. - JvmtiThreadState *state = ((JavaThread*)thread)->jvmti_thread_state(); + JvmtiThreadState *state = thread->as_Java_thread()->jvmti_thread_state(); if (state != NULL) { // state is non NULL when SampledObjectAllocEventCollector is enabled. JvmtiSampledObjectAllocEventCollector *collector; @@ -2407,7 +2407,7 @@ void JvmtiExport::post_data_dump() { } void JvmtiExport::post_monitor_contended_enter(JavaThread *thread, ObjectMonitor *obj_mntr) { - oop object = (oop)obj_mntr->object(); + oop object = obj_mntr->object(); JvmtiThreadState *state = thread->jvmti_thread_state(); if (state == NULL) { return; @@ -2438,7 +2438,7 @@ void JvmtiExport::post_monitor_contended_enter(JavaThread *thread, ObjectMonitor } void JvmtiExport::post_monitor_contended_entered(JavaThread *thread, ObjectMonitor *obj_mntr) { - oop object = (oop)obj_mntr->object(); + oop object = obj_mntr->object(); JvmtiThreadState *state = thread->jvmti_thread_state(); if (state == NULL) { return; @@ -2501,7 +2501,7 @@ void JvmtiExport::post_monitor_wait(JavaThread *thread, oop object, } void JvmtiExport::post_monitor_waited(JavaThread *thread, ObjectMonitor *obj_mntr, jboolean timed_out) { - oop object = (oop)obj_mntr->object(); + oop object = obj_mntr->object(); JvmtiThreadState *state = thread->jvmti_thread_state(); if (state == NULL) { return; @@ -2867,7 +2867,7 @@ NoJvmtiVMObjectAllocMark::NoJvmtiVMObjectAllocMark() : _collector(NULL) { } Thread* thread = Thread::current_or_null(); if (thread != NULL && thread->is_Java_thread()) { - JavaThread* current_thread = (JavaThread*)thread; + JavaThread* current_thread = thread->as_Java_thread(); JvmtiThreadState *state = current_thread->jvmti_thread_state(); if (state != NULL) { JvmtiVMObjectAllocEventCollector *collector; diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp index 7d64a88efff..68f589ac3d2 100644 --- a/src/hotspot/share/prims/jvmtiImpl.cpp +++ b/src/hotspot/share/prims/jvmtiImpl.cpp @@ -73,7 +73,6 @@ JvmtiAgentThread::start_function_wrapper(JavaThread *thread, TRAPS) { // It is expected that any Agent threads will be created as // Java Threads. If this is the case, notification of the creation // of the thread is given in JavaThread::thread_main(). - assert(thread->is_Java_thread(), "debugger thread should be a Java Thread"); assert(thread == JavaThread::current(), "sanity check"); JvmtiAgentThread *dthread = (JvmtiAgentThread *)thread; diff --git a/src/hotspot/share/prims/jvmtiRawMonitor.cpp b/src/hotspot/share/prims/jvmtiRawMonitor.cpp index 0e8d38498fc..06efea26c5f 100644 --- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp +++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -234,7 +234,7 @@ int JvmtiRawMonitor::simple_wait(Thread* self, jlong millis) { int ret = M_OK; if (self->is_Java_thread()) { - JavaThread* jt = (JavaThread*) self; + JavaThread* jt = self->as_Java_thread(); // Transition to VM so we can check interrupt state ThreadInVMfromNative tivm(jt); if (jt->is_interrupted(true)) { @@ -314,7 +314,7 @@ void JvmtiRawMonitor::raw_enter(Thread* self) { // don't enter raw monitor if thread is being externally suspended, it will // surprise the suspender if a "suspended" thread can still enter monitor if (self->is_Java_thread()) { - jt = (JavaThread*)self; + jt = self->as_Java_thread(); jt->SR_lock()->lock_without_safepoint_check(); while (jt->is_external_suspend()) { jt->SR_lock()->unlock(); @@ -410,7 +410,7 @@ int JvmtiRawMonitor::raw_wait(jlong millis, Thread* self) { guarantee(self == _owner, "invariant"); if (self->is_Java_thread()) { - JavaThread* jt = (JavaThread*)self; + JavaThread* jt = self->as_Java_thread(); for (;;) { jt->set_suspend_equivalent(); if (!jt->handle_special_suspend_equivalent_condition()) { diff --git a/src/hotspot/share/prims/jvmtiThreadState.cpp b/src/hotspot/share/prims/jvmtiThreadState.cpp index 5c80a2c6b68..2bcf10689e1 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.cpp +++ b/src/hotspot/share/prims/jvmtiThreadState.cpp @@ -241,7 +241,7 @@ int JvmtiThreadState::count_frames() { void JvmtiThreadState::invalidate_cur_stack_depth() { assert(SafepointSynchronize::is_at_safepoint() || - (JavaThread *)Thread::current() == get_thread() || + JavaThread::current() == get_thread() || Thread::current() == get_thread()->active_handshaker(), "bad synchronization with owner thread"); @@ -272,7 +272,7 @@ void JvmtiThreadState::decr_cur_stack_depth() { } int JvmtiThreadState::cur_stack_depth() { - Thread *current = Thread::current(); + JavaThread *current = JavaThread::current(); guarantee(current == get_thread() || current == get_thread()->active_handshaker(), "must be current thread or direct handshake"); diff --git a/src/hotspot/share/prims/jvmtiTrace.cpp b/src/hotspot/share/prims/jvmtiTrace.cpp index fd8c85cae36..e620c996c93 100644 --- a/src/hotspot/share/prims/jvmtiTrace.cpp +++ b/src/hotspot/share/prims/jvmtiTrace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -276,8 +276,7 @@ const char *JvmtiTrace::safe_get_thread_name(Thread *thread) { if (!thread->is_Java_thread()) { return thread->name(); } - JavaThread *java_thread = (JavaThread *)thread; - oop threadObj = java_thread->threadObj(); + oop threadObj = thread->as_Java_thread()->threadObj(); if (threadObj == NULL) { return "NULL"; } diff --git a/src/hotspot/share/prims/stackwalk.cpp b/src/hotspot/share/prims/stackwalk.cpp index f7f4f0d4ca4..6c0b973058a 100644 --- a/src/hotspot/share/prims/stackwalk.cpp +++ b/src/hotspot/share/prims/stackwalk.cpp @@ -79,7 +79,6 @@ void JavaFrameStream::next() { _vfst.next();} BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array) { - assert(thread != NULL && thread->is_Java_thread(), ""); oop m1 = frames_array->obj_at(magic_pos); if (m1 != thread->threadObj()) return NULL; if (magic == 0L) return NULL; @@ -338,7 +337,7 @@ oop StackWalk::walk(Handle stackStream, jlong mode, objArrayHandle frames_array, TRAPS) { ResourceMark rm(THREAD); - JavaThread* jt = (JavaThread*)THREAD; + JavaThread* jt = THREAD->as_Java_thread(); log_debug(stackwalk)("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d", mode, skip_frames, frame_count); @@ -458,7 +457,7 @@ jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic, objArrayHandle frames_array, TRAPS) { - JavaThread* jt = (JavaThread*)THREAD; + JavaThread* jt = THREAD->as_Java_thread(); BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array); if (existing_stream == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 6440de7f829..586c2b7d9cc 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -1997,8 +1997,7 @@ WB_ENTRY(jint, WB_HandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_han jint _num_threads_completed; void do_thread(Thread* th) { - assert(th->is_Java_thread(), "sanity"); - JavaThread* jt = (JavaThread*)th; + JavaThread* jt = th->as_Java_thread(); ResourceMark rm; jt->print_on(tty); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 9b6a60db41c..adf05cc4231 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1459,7 +1459,14 @@ bool Arguments::add_property(const char* prop, PropertyWriteable writeable, Prop if (is_internal_module_property(key) || strcmp(key, "jdk.module.main") == 0) { MetaspaceShared::disable_optimized_module_handling(); - log_info(cds)("Using optimized module handling disabled due to incompatible property: %s=%s", key, value); + log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value); + } + if (strcmp(key, "jdk.module.showModuleResolution") == 0 || + strcmp(key, "jdk.module.illegalAccess") == 0 || + strcmp(key, "jdk.module.validation") == 0 || + strcmp(key, "java.system.class.loader") == 0) { + MetaspaceShared::disable_full_module_graph(); + log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value); } #endif @@ -2508,7 +2515,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m Arguments::append_sysclasspath(tail); #if INCLUDE_CDS MetaspaceShared::disable_optimized_module_handling(); - log_info(cds)("Using optimized module handling disabled due to bootclasspath was appended"); + log_info(cds)("optimized module handling: disabled because bootclasspath was appended"); #endif // -bootclasspath/p: } else if (match_option(option, "-Xbootclasspath/p:", &tail)) { @@ -3898,10 +3905,7 @@ bool Arguments::handle_deprecated_print_gc_flags() { jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { assert(verify_special_jvm_flags(false), "deprecated and obsolete flag table inconsistent"); - - // Initialize ranges and constraints - JVMFlagRangeList::init(); - JVMFlagConstraintList::init(); + JVMFlag::check_all_flag_declarations(); // If flag "-XX:Flags=flags-file" is used it will be the first option to be processed. const char* hotspotrc = ".hotspotrc"; diff --git a/src/hotspot/share/runtime/biasedLocking.cpp b/src/hotspot/share/runtime/biasedLocking.cpp index fa39d0b91a2..9d4a03834b8 100644 --- a/src/hotspot/share/runtime/biasedLocking.cpp +++ b/src/hotspot/share/runtime/biasedLocking.cpp @@ -725,8 +725,7 @@ void BiasedLocking::walk_stack_and_revoke(oop obj, JavaThread* biased_locker) { } void BiasedLocking::revoke_own_lock(Handle obj, TRAPS) { - assert(THREAD->is_Java_thread(), "must be called by a JavaThread"); - JavaThread* thread = (JavaThread*)THREAD; + JavaThread* thread = THREAD->as_Java_thread(); markWord mark = obj->mark(); @@ -740,7 +739,7 @@ void BiasedLocking::revoke_own_lock(Handle obj, TRAPS) { ResourceMark rm; log_info(biasedlocking)("Revoking bias by walking my own stack:"); EventBiasedLockSelfRevocation event; - BiasedLocking::walk_stack_and_revoke(obj(), (JavaThread*) thread); + BiasedLocking::walk_stack_and_revoke(obj(), thread); thread->set_cached_monitor_info(NULL); assert(!obj->mark().has_bias_pattern(), "invariant"); if (event.should_commit()) { @@ -830,7 +829,7 @@ void BiasedLocking::revoke(Handle obj, TRAPS) { } return; } else { - BiasedLocking::Condition cond = single_revoke_with_handshake(obj, (JavaThread*)THREAD, blt); + BiasedLocking::Condition cond = single_revoke_with_handshake(obj, THREAD->as_Java_thread(), blt); if (cond != NOT_REVOKED) { return; } @@ -839,7 +838,7 @@ void BiasedLocking::revoke(Handle obj, TRAPS) { assert((heuristics == HR_BULK_REVOKE) || (heuristics == HR_BULK_REBIAS), "?"); EventBiasedLockClassRevocation event; - VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*)THREAD, + VM_BulkRevokeBias bulk_revoke(&obj, THREAD->as_Java_thread(), (heuristics == HR_BULK_REBIAS)); VMThread::execute(&bulk_revoke); if (event.should_commit()) { diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 8e88fda441b..7e9d23e9c6a 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -810,7 +810,7 @@ class DeoptimizeMarkedClosure : public HandshakeClosure { public: DeoptimizeMarkedClosure() : HandshakeClosure("Deoptimize") {} void do_thread(Thread* thread) { - JavaThread* jt = (JavaThread*)thread; + JavaThread* jt = thread->as_Java_thread(); jt->deoptimize_marked_methods(); } }; @@ -1697,8 +1697,7 @@ void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool // to the runtime the stack is no longer guarded. Reguard the // stack otherwise if we return to the uncommon trap blob and the // stack bang causes a stack overflow we crash. - assert(THREAD->is_Java_thread(), "only a java thread can be here"); - JavaThread* thread = (JavaThread*)THREAD; + JavaThread* thread = THREAD->as_Java_thread(); bool guard_pages_enabled = thread->stack_guards_enabled(); if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack(); assert(guard_pages_enabled, "stack banging in uncommon trap blob may cause crash"); diff --git a/src/hotspot/share/runtime/flags/jvmFlag.cpp b/src/hotspot/share/runtime/flags/jvmFlag.cpp index 4611155d7ee..4d44a58a34c 100644 --- a/src/hotspot/share/runtime/flags/jvmFlag.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlag.cpp @@ -28,6 +28,7 @@ #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlag.hpp" #include "runtime/flags/jvmFlagConstraintList.hpp" +#include "runtime/flags/jvmFlagLookup.hpp" #include "runtime/flags/jvmFlagRangeList.hpp" #include "runtime/globals_extension.hpp" #include "utilities/defaultStream.hpp" @@ -131,7 +132,7 @@ bool JVMFlag::ccstr_accumulates() const { return strcmp(_type, "ccstrlist") == 0; } -JVMFlag::Flags JVMFlag::get_origin() { +JVMFlag::Flags JVMFlag::get_origin() const { return Flags(_flags & VALUE_ORIGIN_MASK); } @@ -141,19 +142,19 @@ void JVMFlag::set_origin(Flags origin) { _flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | new_origin); } -bool JVMFlag::is_default() { +bool JVMFlag::is_default() const { return (get_origin() == DEFAULT); } -bool JVMFlag::is_ergonomic() { +bool JVMFlag::is_ergonomic() const { return (get_origin() == ERGONOMIC); } -bool JVMFlag::is_command_line() { +bool JVMFlag::is_command_line() const { return (_flags & ORIG_COMMAND_LINE) != 0; } -bool JVMFlag::is_jimage_resource() { +bool JVMFlag::is_jimage_resource() const { return (get_origin() == JIMAGE_RESOURCE); } @@ -185,10 +186,6 @@ bool JVMFlag::is_develop() const { return (_flags & KIND_DEVELOP) != 0; } -bool JVMFlag::is_read_write() const { - return (_flags & KIND_READ_WRITE) != 0; -} - /** * Returns if this flag is a constant in the binary. Right now this is * true for notproduct and develop flags in product builds. @@ -224,13 +221,13 @@ void JVMFlag::clear_diagnostic() { void JVMFlag::clear_experimental() { assert(is_experimental(), "sanity"); - _flags = Flags(_flags & ~KIND_EXPERIMENTAL); + _flags = Flags(_flags & ~KIND_EXPERIMENTAL); assert(!is_experimental(), "sanity"); } void JVMFlag::set_product() { assert(!is_product(), "sanity"); - _flags = Flags(_flags | KIND_PRODUCT); + _flags = Flags(_flags | KIND_PRODUCT); assert(is_product(), "sanity"); } @@ -266,7 +263,7 @@ JVMFlag::MsgType JVMFlag::get_locked_message(char* buf, int buflen) const { } bool JVMFlag::is_writeable() const { - return is_manageable() || (is_product() && is_read_write()); + return is_manageable(); } // All flags except "manageable" are assumed to be internal flags. @@ -288,7 +285,7 @@ void fill_to_pos(outputStream* st, unsigned int req_pos) { } } -void JVMFlag::print_on(outputStream* st, bool withComments, bool printRanges) { +void JVMFlag::print_on(outputStream* st, bool withComments, bool printRanges) const { // Don't print notproduct and develop flags in a product build. if (is_constant_in_binary()) { return; @@ -496,7 +493,7 @@ void JVMFlag::print_on(outputStream* st, bool withComments, bool printRanges) { } } -void JVMFlag::print_kind(outputStream* st, unsigned int width) { +void JVMFlag::print_kind(outputStream* st, unsigned int width) const { struct Data { int flag; const char* name; @@ -515,7 +512,6 @@ void JVMFlag::print_kind(outputStream* st, unsigned int width) { { KIND_NOT_PRODUCT, "notproduct" }, { KIND_DEVELOP, "develop" }, { KIND_LP64_PRODUCT, "lp64_product" }, - { KIND_READ_WRITE, "rw" }, { -1, "" } }; @@ -549,7 +545,7 @@ void JVMFlag::print_kind(outputStream* st, unsigned int width) { } } -void JVMFlag::print_origin(outputStream* st, unsigned int width) { +void JVMFlag::print_origin(outputStream* st, unsigned int width) const { int origin = _flags & VALUE_ORIGIN_MASK; st->print("{"); switch(origin) { @@ -578,7 +574,7 @@ void JVMFlag::print_origin(outputStream* st, unsigned int width) { st->print("}"); } -void JVMFlag::print_as_flag(outputStream* st) { +void JVMFlag::print_as_flag(outputStream* st) const { if (is_bool()) { st->print("-XX:%s%s", get_bool() ? "+" : "-", _name); } else if (is_int()) { @@ -633,167 +629,125 @@ const char* JVMFlag::flag_error_str(JVMFlag::Error error) { } } -// 4991491 do not "optimize out" the was_set false values: omitting them -// tickles a Microsoft compiler bug causing flagTable to be malformed - -#define RUNTIME_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT) }, -#define RUNTIME_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define RUNTIME_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DIAGNOSTIC) }, -#define RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_EXPERIMENTAL) }, -#define RUNTIME_MANAGEABLE_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_MANAGEABLE) }, -#define RUNTIME_PRODUCT_RW_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_READ_WRITE) }, -#define RUNTIME_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DEVELOP) }, -#define RUNTIME_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define RUNTIME_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_NOT_PRODUCT) }, - -#define JVMCI_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_PRODUCT) }, -#define JVMCI_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define JVMCI_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DIAGNOSTIC) }, -#define JVMCI_PD_DIAGNOSTIC_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define JVMCI_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_EXPERIMENTAL) }, -#define JVMCI_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DEVELOP) }, -#define JVMCI_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define JVMCI_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_NOT_PRODUCT) }, - -#ifdef _LP64 -#define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_LP64_PRODUCT) }, -#else -#define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ -#endif // _LP64 - -#define C1_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_PRODUCT) }, -#define C1_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define C1_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DIAGNOSTIC) }, -#define C1_PD_DIAGNOSTIC_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define C1_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DEVELOP) }, -#define C1_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define C1_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_NOT_PRODUCT) }, - -#define C2_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_PRODUCT) }, -#define C2_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define C2_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DIAGNOSTIC) }, -#define C2_PD_DIAGNOSTIC_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define C2_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_EXPERIMENTAL) }, -#define C2_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DEVELOP) }, -#define C2_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) }, -#define C2_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_NOT_PRODUCT) }, - -#define ARCH_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_PRODUCT) }, -#define ARCH_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_DIAGNOSTIC) }, -#define ARCH_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_EXPERIMENTAL) }, -#define ARCH_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_DEVELOP) }, -#define ARCH_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_NOT_PRODUCT) }, - -static JVMFlag flagTable[] = { - VM_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \ - RUNTIME_PD_DEVELOP_FLAG_STRUCT, \ - RUNTIME_PRODUCT_FLAG_STRUCT, \ - RUNTIME_PD_PRODUCT_FLAG_STRUCT, \ - RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \ - RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \ - RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \ - RUNTIME_NOTPRODUCT_FLAG_STRUCT, \ - RUNTIME_MANAGEABLE_FLAG_STRUCT, \ - RUNTIME_PRODUCT_RW_FLAG_STRUCT, \ - RUNTIME_LP64_PRODUCT_FLAG_STRUCT, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT) - - RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \ - RUNTIME_PD_DEVELOP_FLAG_STRUCT, \ - RUNTIME_PRODUCT_FLAG_STRUCT, \ - RUNTIME_PD_PRODUCT_FLAG_STRUCT, \ - RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \ - RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \ - RUNTIME_NOTPRODUCT_FLAG_STRUCT, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT) -#if INCLUDE_JVMCI - JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, \ - JVMCI_PD_DEVELOP_FLAG_STRUCT, \ - JVMCI_PRODUCT_FLAG_STRUCT, \ - JVMCI_PD_PRODUCT_FLAG_STRUCT, \ - JVMCI_DIAGNOSTIC_FLAG_STRUCT, \ - JVMCI_PD_DIAGNOSTIC_FLAG_STRUCT, \ - JVMCI_EXPERIMENTAL_FLAG_STRUCT, \ - JVMCI_NOTPRODUCT_FLAG_STRUCT, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT) -#endif // INCLUDE_JVMCI -#ifdef COMPILER1 - C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, \ - C1_PD_DEVELOP_FLAG_STRUCT, \ - C1_PRODUCT_FLAG_STRUCT, \ - C1_PD_PRODUCT_FLAG_STRUCT, \ - C1_DIAGNOSTIC_FLAG_STRUCT, \ - C1_PD_DIAGNOSTIC_FLAG_STRUCT, \ - C1_NOTPRODUCT_FLAG_STRUCT, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT) -#endif // COMPILER1 -#ifdef COMPILER2 - C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, \ - C2_PD_DEVELOP_FLAG_STRUCT, \ - C2_PRODUCT_FLAG_STRUCT, \ - C2_PD_PRODUCT_FLAG_STRUCT, \ - C2_DIAGNOSTIC_FLAG_STRUCT, \ - C2_PD_DIAGNOSTIC_FLAG_STRUCT, \ - C2_EXPERIMENTAL_FLAG_STRUCT, \ - C2_NOTPRODUCT_FLAG_STRUCT, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT) -#endif // COMPILER2 - ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, \ - ARCH_PRODUCT_FLAG_STRUCT, \ - ARCH_DIAGNOSTIC_FLAG_STRUCT, \ - ARCH_EXPERIMENTAL_FLAG_STRUCT, \ - ARCH_NOTPRODUCT_FLAG_STRUCT, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT) - {0, NULL, NULL} +//---------------------------------------------------------------------- +// Build flagTable[] + +// Find out the number of LP64/JVMCI/COMPILER1/COMPILER1/ARCH flags, +// for JVMFlag::flag_group() + +#define ENUM_F(type, name, ...) enum_##name, +#define IGNORE_F(...) + +// dev dev-pd pro pro-pd notpro range constraint +enum FlagCounter_LP64 { LP64_RUNTIME_FLAGS( ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F) num_flags_LP64 }; +enum FlagCounter_JVMCI { JVMCI_ONLY(JVMCI_FLAGS( ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F)) num_flags_JVMCI }; +enum FlagCounter_C1 { COMPILER1_PRESENT(C1_FLAGS(ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F)) num_flags_C1 }; +enum FlagCounter_C2 { COMPILER2_PRESENT(C2_FLAGS(ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F)) num_flags_C2 }; +enum FlagCounter_ARCH { ARCH_FLAGS( ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F) num_flags_ARCH }; + +const int first_flag_enum_LP64 = 0; +const int first_flag_enum_JVMCI = first_flag_enum_LP64 + num_flags_LP64; +const int first_flag_enum_C1 = first_flag_enum_JVMCI + num_flags_JVMCI; +const int first_flag_enum_C2 = first_flag_enum_C1 + num_flags_C1; +const int first_flag_enum_ARCH = first_flag_enum_C2 + num_flags_C2; +const int first_flag_enum_other = first_flag_enum_ARCH + num_flags_ARCH; + +static constexpr int flag_group(int flag_enum) { + if (flag_enum < first_flag_enum_JVMCI) return JVMFlag::KIND_LP64_PRODUCT; + if (flag_enum < first_flag_enum_C1) return JVMFlag::KIND_JVMCI; + if (flag_enum < first_flag_enum_C2) return JVMFlag::KIND_C1; + if (flag_enum < first_flag_enum_ARCH) return JVMFlag::KIND_C2; + if (flag_enum < first_flag_enum_other) return JVMFlag::KIND_ARCH; + + return 0; +} + +constexpr JVMFlag::JVMFlag(int flag_enum, const char* type, const char* name, + void* addr, int flags, int extra_flags, const char* doc) : + _type(type), _name(name), _addr(addr), _flags() NOT_PRODUCT(COMMA _doc(doc)) { + flags = flags | extra_flags | JVMFlag::DEFAULT | flag_group(flag_enum); + if ((flags & JVMFlag::KIND_PRODUCT) != 0) { + if (flags & (JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_MANAGEABLE | JVMFlag::KIND_EXPERIMENTAL)) { + // Backwards compatibility. This will be relaxed in JDK-7123237. + flags &= ~(JVMFlag::KIND_PRODUCT); + } + } + _flags = static_cast<Flags>(flags); +} + +constexpr JVMFlag::JVMFlag(int flag_enum, const char* type, const char* name, + void* addr, int flags, const char* doc) : + JVMFlag(flag_enum, type, name, addr, flags, /*extra_flags*/0, doc) {} + +const int PRODUCT_KIND = JVMFlag::KIND_PRODUCT; +const int PRODUCT_KIND_PD = JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT; +const int DEVELOP_KIND = JVMFlag::KIND_DEVELOP; +const int DEVELOP_KIND_PD = JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT; +const int NOTPROD_KIND = JVMFlag::KIND_NOT_PRODUCT; + +#define DEVELOP_FLAG_INIT( type, name, value, ...) JVMFlag(FLAG_MEMBER_ENUM(name), #type, XSTR(name), (void*)&name, DEVELOP_KIND, __VA_ARGS__), +#define DEVELOP_FLAG_INIT_PD(type, name, ...) JVMFlag(FLAG_MEMBER_ENUM(name), #type, XSTR(name), (void*)&name, DEVELOP_KIND_PD, __VA_ARGS__), +#define PRODUCT_FLAG_INIT( type, name, value, ...) JVMFlag(FLAG_MEMBER_ENUM(name), #type, XSTR(name), (void*)&name, PRODUCT_KIND, __VA_ARGS__), +#define PRODUCT_FLAG_INIT_PD(type, name, ...) JVMFlag(FLAG_MEMBER_ENUM(name), #type, XSTR(name), (void*)&name, PRODUCT_KIND_PD, __VA_ARGS__), +#define NOTPROD_FLAG_INIT( type, name, value, ...) JVMFlag(FLAG_MEMBER_ENUM(name), #type, XSTR(name), (void*)&name, NOTPROD_KIND, __VA_ARGS__), + +// Handy aliases to match the symbols used in the flag specification macros. +const int DIAGNOSTIC = JVMFlag::KIND_DIAGNOSTIC; +const int MANAGEABLE = JVMFlag::KIND_MANAGEABLE; +const int EXPERIMENTAL = JVMFlag::KIND_EXPERIMENTAL; + +#define MATERIALIZE_ALL_FLAGS \ + ALL_FLAGS(DEVELOP_FLAG_INIT, \ + DEVELOP_FLAG_INIT_PD, \ + PRODUCT_FLAG_INIT, \ + PRODUCT_FLAG_INIT_PD, \ + NOTPROD_FLAG_INIT, \ + IGNORE_RANGE, \ + IGNORE_CONSTRAINT) + +static JVMFlag flagTable[NUM_JVMFlagsEnum + 1] = { + MATERIALIZE_ALL_FLAGS + JVMFlag() // The iteration code wants a flag with a NULL name at the end of the table. }; +// We want flagTable[] to be completely initialized at C++ compilation time, which requires +// that all arguments passed to JVMFlag() constructors be constexpr. The following line +// checks for this -- if any non-constexpr arguments are passed, the C++ compiler will +// generate an error. +// +// constexpr implies internal linkage. This means the flagTable_verify_constexpr[] variable +// will not be included in jvmFlag.o, so there's no footprint cost for having this variable. +// +// Note that we cannot declare flagTable[] as constexpr because JVMFlag::_flags is modified +// at runtime. +constexpr JVMFlag flagTable_verify_constexpr[] = { MATERIALIZE_ALL_FLAGS }; + JVMFlag* JVMFlag::flags = flagTable; size_t JVMFlag::numFlags = (sizeof(flagTable) / sizeof(JVMFlag)); -inline bool str_equal(const char* s, size_t s_len, const char* q, size_t q_len) { - if (s_len != q_len) return false; - return memcmp(s, q, q_len) == 0; -} - // Search the flag table for a named flag JVMFlag* JVMFlag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) { - for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) { - if (str_equal(current->_name, current->get_name_length(), name, length)) { - // Found a matching entry. - // Don't report notproduct and develop flags in product builds. - if (current->is_constant_in_binary()) { - return (return_flag ? current : NULL); - } - // Report locked flags only if allowed. - if (!(current->is_unlocked() || current->is_unlocker())) { - if (!allow_locked) { - // disable use of locked flags, e.g. diagnostic, experimental, - // etc. until they are explicitly unlocked - return NULL; - } + JVMFlag* flag = JVMFlagLookup::find(name, length); + if (flag != NULL) { + // Found a matching entry. + // Don't report notproduct and develop flags in product builds. + if (flag->is_constant_in_binary()) { + return (return_flag ? flag : NULL); + } + // Report locked flags only if allowed. + if (!(flag->is_unlocked() || flag->is_unlocker())) { + if (!allow_locked) { + // disable use of locked flags, e.g. diagnostic, experimental, + // etc. until they are explicitly unlocked + return NULL; } - return current; } + return flag; } // JVMFlag name is not in the flag table return NULL; } -// Get or compute the flag name length -size_t JVMFlag::get_name_length() { - if (_name_len == 0) { - _name_len = strlen(_name); - } - return _name_len; -} - JVMFlag* JVMFlag::fuzzy_match(const char* name, size_t length, bool allow_locked) { float VMOptionsFuzzyMatchSimilarity = 0.7f; JVMFlag* match = NULL; @@ -856,7 +810,7 @@ void JVMFlagEx::setOnCmdLine(JVMFlagsEnum flag) { } template<class E, class T> -static void trace_flag_changed(const JVMFlag* flag, const T old_value, const T new_value, const JVMFlag::Flags origin) { +static void trace_flag_changed(JVMFlag* flag, const T old_value, const T new_value, const JVMFlag::Flags origin) { E e; e.set_name(flag->_name); e.set_oldValue(old_value); @@ -865,11 +819,11 @@ static void trace_flag_changed(const JVMFlag* flag, const T old_value, const T n e.commit(); } -static JVMFlag::Error apply_constraint_and_check_range_bool(const JVMFlag* flag, bool new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_bool(JVMFlag* flag, bool new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_bool(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_bool(new_value, verbose); } return status; } @@ -900,16 +854,16 @@ JVMFlag::Error JVMFlagEx::boolAtPut(JVMFlagsEnum flag, bool value, JVMFlag::Flag return JVMFlag::boolAtPut(faddr, &value, origin); } -static JVMFlag::Error apply_constraint_and_check_range_int(const JVMFlag* flag, int new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_int(JVMFlag* flag, int new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - status = range->check_int(new_value, verbose); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + status = range.check_int(new_value, verbose); } if (status == JVMFlag::SUCCESS) { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_int(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_int(new_value, verbose); } } return status; @@ -941,16 +895,16 @@ JVMFlag::Error JVMFlagEx::intAtPut(JVMFlagsEnum flag, int value, JVMFlag::Flags return JVMFlag::intAtPut(faddr, &value, origin); } -static JVMFlag::Error apply_constraint_and_check_range_uint(const JVMFlag* flag, uint new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_uint(JVMFlag* flag, uint new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - status = range->check_uint(new_value, verbose); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + status = range.check_uint(new_value, verbose); } if (status == JVMFlag::SUCCESS) { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_uint(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_uint(new_value, verbose); } } return status; @@ -989,16 +943,16 @@ JVMFlag::Error JVMFlag::intxAt(const JVMFlag* flag, intx* value) { return JVMFlag::SUCCESS; } -static JVMFlag::Error apply_constraint_and_check_range_intx(const JVMFlag* flag, intx new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_intx(JVMFlag* flag, intx new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - status = range->check_intx(new_value, verbose); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + status = range.check_intx(new_value, verbose); } if (status == JVMFlag::SUCCESS) { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_intx(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_intx(new_value, verbose); } } return status; @@ -1030,16 +984,16 @@ JVMFlag::Error JVMFlag::uintxAt(const JVMFlag* flag, uintx* value) { return JVMFlag::SUCCESS; } -static JVMFlag::Error apply_constraint_and_check_range_uintx(const JVMFlag* flag, uintx new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_uintx(JVMFlag* flag, uintx new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - status = range->check_uintx(new_value, verbose); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + status = range.check_uintx(new_value, verbose); } if (status == JVMFlag::SUCCESS) { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_uintx(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_uintx(new_value, verbose); } } return status; @@ -1071,16 +1025,16 @@ JVMFlag::Error JVMFlag::uint64_tAt(const JVMFlag* flag, uint64_t* value) { return JVMFlag::SUCCESS; } -static JVMFlag::Error apply_constraint_and_check_range_uint64_t(const JVMFlag* flag, uint64_t new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_uint64_t(JVMFlag* flag, uint64_t new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - status = range->check_uint64_t(new_value, verbose); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + status = range.check_uint64_t(new_value, verbose); } if (status == JVMFlag::SUCCESS) { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_uint64_t(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_uint64_t(new_value, verbose); } } return status; @@ -1112,16 +1066,16 @@ JVMFlag::Error JVMFlag::size_tAt(const JVMFlag* flag, size_t* value) { return JVMFlag::SUCCESS; } -static JVMFlag::Error apply_constraint_and_check_range_size_t(const JVMFlag* flag, size_t new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_size_t(JVMFlag* flag, size_t new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - status = range->check_size_t(new_value, verbose); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + status = range.check_size_t(new_value, verbose); } if (status == JVMFlag::SUCCESS) { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_size_t(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_size_t(new_value, verbose); } } return status; @@ -1154,16 +1108,16 @@ JVMFlag::Error JVMFlag::doubleAt(const JVMFlag* flag, double* value) { return JVMFlag::SUCCESS; } -static JVMFlag::Error apply_constraint_and_check_range_double(const JVMFlag* flag, double new_value, bool verbose) { +static JVMFlag::Error apply_constraint_and_check_range_double(JVMFlag* flag, double new_value, bool verbose) { JVMFlag::Error status = JVMFlag::SUCCESS; - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - status = range->check_double(new_value, verbose); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + status = range.check_double(new_value, verbose); } if (status == JVMFlag::SUCCESS) { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag); - if (constraint != NULL) { - status = constraint->apply_double(new_value, verbose); + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find_if_needs_check(flag); + if (constraint.exists()) { + status = constraint.apply_double(new_value, verbose); } } return status; @@ -1269,6 +1223,33 @@ void JVMFlag::verify() { #endif // PRODUCT +#ifdef ASSERT + +void JVMFlag::assert_valid_flag_enum(int i) { + assert(0 <= i && i < NUM_JVMFlagsEnum, "must be"); +} + +void JVMFlag::check_all_flag_declarations() { + for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) { + int flags = static_cast<int>(current->_flags); + // Backwards compatibility. This will be relaxed/removed in JDK-7123237. + int mask = JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_MANAGEABLE | JVMFlag::KIND_EXPERIMENTAL; + if ((flags & mask) != 0) { + assert((flags & mask) == JVMFlag::KIND_DIAGNOSTIC || + (flags & mask) == JVMFlag::KIND_MANAGEABLE || + (flags & mask) == JVMFlag::KIND_EXPERIMENTAL, + "%s can be declared with at most one of " + "DIAGNOSTIC, MANAGEABLE or EXPERIMENTAL", current->_name); + assert((flags & KIND_NOT_PRODUCT) == 0 && + (flags & KIND_DEVELOP) == 0, + "%s has an optional DIAGNOSTIC, MANAGEABLE or EXPERIMENTAL " + "attribute; it must be declared as a product flag", current->_name); + } + } +} + +#endif // ASSERT + void JVMFlag::printFlags(outputStream* out, bool withComments, bool printRanges, bool skipDefaults) { // Print the flags sorted by name // Note: This method may be called before the thread structure is in place diff --git a/src/hotspot/share/runtime/flags/jvmFlag.hpp b/src/hotspot/share/runtime/flags/jvmFlag.hpp index 1c84920896d..7e8731e49de 100644 --- a/src/hotspot/share/runtime/flags/jvmFlag.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlag.hpp @@ -34,7 +34,7 @@ class outputStream; typedef const char* (*RangeStrFunc)(void); struct JVMFlag { - enum Flags { + enum Flags : int { // latest value origin DEFAULT = 0, COMMAND_LINE = 1, @@ -58,12 +58,11 @@ struct JVMFlag { KIND_NOT_PRODUCT = 1 << 8, KIND_DEVELOP = 1 << 9, KIND_PLATFORM_DEPENDENT = 1 << 10, - KIND_READ_WRITE = 1 << 11, - KIND_C1 = 1 << 12, - KIND_C2 = 1 << 13, - KIND_ARCH = 1 << 14, - KIND_LP64_PRODUCT = 1 << 15, - KIND_JVMCI = 1 << 16, + KIND_C1 = 1 << 11, + KIND_C2 = 1 << 12, + KIND_ARCH = 1 << 13, + KIND_LP64_PRODUCT = 1 << 14, + KIND_JVMCI = 1 << 15, // set this bit if the flag was set on the command line ORIG_COMMAND_LINE = 1 << 17, @@ -109,9 +108,8 @@ struct JVMFlag { const char* _type; const char* _name; void* _addr; - NOT_PRODUCT(const char* _doc;) Flags _flags; - size_t _name_len; + NOT_PRODUCT(const char* _doc;) // points to all Flags static array static JVMFlag* flags; @@ -123,13 +121,21 @@ struct JVMFlag { static JVMFlag* find_flag(const char* name, size_t length, bool allow_locked, bool return_flag); public: + constexpr JVMFlag() : _type(), _name(), _addr(), _flags() NOT_PRODUCT(COMMA _doc()) {} + + constexpr JVMFlag(int flag_enum, const char* type, const char* name, + void* addr, int flags, int extra_flags, const char* doc); + + constexpr JVMFlag(int flag_enum, const char* type, const char* name, + void* addr, int flags, const char* doc); + static JVMFlag* find_flag(const char* name) { return find_flag(name, strlen(name), false, false); } - static const JVMFlag* find_declared_flag(const char* name, size_t length) { + static JVMFlag* find_declared_flag(const char* name, size_t length) { return find_flag(name, length, true, true); } - static const JVMFlag* find_declared_flag(const char* name) { + static JVMFlag* find_declared_flag(const char* name) { return find_declared_flag(name, strlen(name)); } @@ -143,52 +149,64 @@ struct JVMFlag { static const char* get_size_t_default_range_str(); static const char* get_double_default_range_str(); + static void assert_valid_flag_enum(int i) NOT_DEBUG_RETURN; + static void check_all_flag_declarations() NOT_DEBUG_RETURN; + + inline int flag_enum() const { + int i = this - JVMFlag::flags; + assert_valid_flag_enum(i); + return i; + } + + static JVMFlag* flag_from_enum(int flag_enum) { + assert_valid_flag_enum(flag_enum); + return &JVMFlag::flags[flag_enum]; + } + bool is_bool() const; bool get_bool() const { return *((bool*) _addr); } - void set_bool(bool value) { *((bool*) _addr) = value; } + void set_bool(bool value) const { *((bool*) _addr) = value; } bool is_int() const; int get_int() const { return *((int*) _addr); } - void set_int(int value) { *((int*) _addr) = value; } + void set_int(int value) const { *((int*) _addr) = value; } bool is_uint() const; uint get_uint() const { return *((uint*) _addr); } - void set_uint(uint value) { *((uint*) _addr) = value; } + void set_uint(uint value) const { *((uint*) _addr) = value; } bool is_intx() const; intx get_intx() const { return *((intx*) _addr); } - void set_intx(intx value) { *((intx*) _addr) = value; } + void set_intx(intx value) const { *((intx*) _addr) = value; } bool is_uintx() const; uintx get_uintx() const { return *((uintx*) _addr); } - void set_uintx(uintx value) { *((uintx*) _addr) = value; } + void set_uintx(uintx value) const { *((uintx*) _addr) = value; } bool is_uint64_t() const; uint64_t get_uint64_t() const { return *((uint64_t*) _addr); } - void set_uint64_t(uint64_t value) { *((uint64_t*) _addr) = value; } + void set_uint64_t(uint64_t value) const { *((uint64_t*) _addr) = value; } bool is_size_t() const; size_t get_size_t() const { return *((size_t*) _addr); } - void set_size_t(size_t value) { *((size_t*) _addr) = value; } + void set_size_t(size_t value) const { *((size_t*) _addr) = value; } bool is_double() const; double get_double() const { return *((double*) _addr); } - void set_double(double value) { *((double*) _addr) = value; } + void set_double(double value) const { *((double*) _addr) = value; } bool is_ccstr() const; bool ccstr_accumulates() const; ccstr get_ccstr() const { return *((ccstr*) _addr); } - void set_ccstr(ccstr value) { *((ccstr*) _addr) = value; } + void set_ccstr(ccstr value) const { *((ccstr*) _addr) = value; } - Flags get_origin(); + Flags get_origin() const; void set_origin(Flags origin); - size_t get_name_length(); - - bool is_default(); - bool is_ergonomic(); - bool is_jimage_resource(); - bool is_command_line(); + bool is_default() const; + bool is_ergonomic() const; + bool is_jimage_resource() const; + bool is_command_line() const; void set_command_line(); bool is_product() const; @@ -197,7 +215,6 @@ struct JVMFlag { bool is_experimental() const; bool is_notproduct() const; bool is_develop() const; - bool is_read_write() const; bool is_constant_in_binary() const; @@ -214,10 +231,10 @@ struct JVMFlag { JVMFlag::MsgType get_locked_message_ext(char*, int) const; // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges - void print_on(outputStream* st, bool withComments = false, bool printRanges = false); - void print_kind(outputStream* st, unsigned int width); - void print_origin(outputStream* st, unsigned int width); - void print_as_flag(outputStream* st); + void print_on(outputStream* st, bool withComments = false, bool printRanges = false) const; + void print_kind(outputStream* st, unsigned int width) const; + void print_origin(outputStream* st, unsigned int width) const; + void print_as_flag(outputStream* st) const; static const char* flag_error_str(JVMFlag::Error error); @@ -260,4 +277,6 @@ struct JVMFlag { static void verify() PRODUCT_RETURN; }; +#define DECLARE_CONSTRAINT(type, func) JVMFlag::Error func(type value, bool verbose); + #endif // SHARE_RUNTIME_FLAGS_JVMFLAG_HPP diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp index 3d21cfdf060..9248eb87521 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp @@ -172,125 +172,43 @@ class JVMFlagConstraint_double : public JVMFlagConstraint { } }; -// No constraint emitting -void emit_constraint_no(...) { /* NOP */ } - -// No constraint emitting if function argument is NOT provided -void emit_constraint_bool(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_ccstr(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_ccstrlist(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_int(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_intx(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_uint(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_uintx(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_uint64_t(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_size_t(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_constraint_double(const JVMFlag* /*flag*/) { /* NOP */ } - -// JVMFlagConstraint emitting code functions if function argument is provided -void emit_constraint_bool(const JVMFlag* flag, JVMFlagConstraintFunc_bool func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_bool(flag, func, type)); -} -void emit_constraint_int(const JVMFlag* flag, JVMFlagConstraintFunc_int func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_int(flag, func, type)); -} -void emit_constraint_intx(const JVMFlag* flag, JVMFlagConstraintFunc_intx func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_intx(flag, func, type)); -} -void emit_constraint_uint(const JVMFlag* flag, JVMFlagConstraintFunc_uint func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_uint(flag, func, type)); -} -void emit_constraint_uintx(const JVMFlag* flag, JVMFlagConstraintFunc_uintx func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_uintx(flag, func, type)); -} -void emit_constraint_uint64_t(const JVMFlag* flag, JVMFlagConstraintFunc_uint64_t func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_uint64_t(flag, func, type)); -} -void emit_constraint_size_t(const JVMFlag* flag, JVMFlagConstraintFunc_size_t func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_size_t(flag, func, type)); -} -void emit_constraint_double(const JVMFlag* flag, JVMFlagConstraintFunc_double func, JVMFlagConstraint::ConstraintType type) { - JVMFlagConstraintList::add(new JVMFlagConstraint_double(flag, func, type)); +#define DEFINE_CONSTRAINT_APPLY(T) \ +JVMFlag::Error JVMFlagConstraintChecker::apply_ ## T(T value, bool verbose) const { \ + assert(exists(), "must be"); \ + JVMFlagConstraint_ ## T constraint(_flag, \ + (JVMFlagConstraintFunc_ ## T)_limit->constraint_func(), \ + (JVMFlagConstraint::ConstraintType)_limit->phase()); \ + return constraint.apply_ ## T(value, verbose); \ } -// Generate code to call emit_constraint_xxx function -#define EMIT_CONSTRAINT_START (void)(0 -#define EMIT_CONSTRAINT(type, name) ); emit_constraint_##type(JVMFlagEx::flag_from_enum(FLAG_MEMBER_ENUM(name)) -#define EMIT_CONSTRAINT_NO ); emit_constraint_no(0 -#define EMIT_CONSTRAINT_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_DIAGNOSTIC_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_EXPERIMENTAL_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_MANAGEABLE_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_PRODUCT_RW_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_PD_PRODUCT_FLAG(type, name, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG(type, name, doc) EMIT_CONSTRAINT(type, name) -#ifndef PRODUCT -#define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc) EMIT_CONSTRAINT(type, name) -#define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#else -#define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc) EMIT_CONSTRAINT_NO -#define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc) EMIT_CONSTRAINT_NO -#define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT_NO -#endif -#ifdef _LP64 -#define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name) -#else -#define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT_NO -#endif -#define EMIT_CONSTRAINT_END ); - -// Generate func argument to pass into emit_constraint_xxx functions -#define EMIT_CONSTRAINT_CHECK(func, type) , func, JVMFlagConstraint::type - -// the "name" argument must be a string literal -#define INITIAL_CONSTRAINTS_SIZE 72 -GrowableArray<JVMFlagConstraint*>* JVMFlagConstraintList::_constraints = NULL; -JVMFlagConstraint::ConstraintType JVMFlagConstraintList::_validating_type = JVMFlagConstraint::AtParse; +ALL_CONSTRAINT_TYPES(DEFINE_CONSTRAINT_APPLY) -// Check the ranges of all flags that have them or print them out and exit if requested -void JVMFlagConstraintList::init(void) { - _constraints = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<JVMFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, mtArguments); - - EMIT_CONSTRAINT_START - - ALL_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, - EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, - EMIT_CONSTRAINT_PRODUCT_FLAG, - EMIT_CONSTRAINT_PD_PRODUCT_FLAG, - EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, - EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG, - EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, - EMIT_CONSTRAINT_NOTPRODUCT_FLAG, - EMIT_CONSTRAINT_MANAGEABLE_FLAG, - EMIT_CONSTRAINT_PRODUCT_RW_FLAG, - EMIT_CONSTRAINT_LP64_PRODUCT_FLAG, - IGNORE_RANGE, - EMIT_CONSTRAINT_CHECK) - - EMIT_CONSTRAINT_END -} -JVMFlagConstraint* JVMFlagConstraintList::find(const JVMFlag* flag) { - JVMFlagConstraint* found = NULL; - for (int i=0; i<length(); i++) { - JVMFlagConstraint* constraint = at(i); - if (constraint->flag() == flag) { - found = constraint; - break; - } +JVMFlag::Error JVMFlagConstraintChecker::apply(bool verbose) const { +#define APPLY_CONSTRAINT(T) \ + if (_flag->is_ ## T()) { \ + JVMFlagConstraint_ ## T constraint(_flag, \ + (JVMFlagConstraintFunc_ ## T)_limit->constraint_func(), \ + (JVMFlagConstraint::ConstraintType)_limit->phase()); \ + return constraint.apply(verbose); \ } - return found; + + ALL_CONSTRAINT_TYPES(APPLY_CONSTRAINT); + + ShouldNotReachHere(); + return JVMFlag::INVALID_FLAG; } + +JVMFlagConstraint::ConstraintType JVMFlagConstraintList::_validating_type = JVMFlagConstraint::AtParse; + // Find constraints and return only if found constraint's type is equal or lower than current validating type. -JVMFlagConstraint* JVMFlagConstraintList::find_if_needs_check(const JVMFlag* flag) { - JVMFlagConstraint* found = NULL; - JVMFlagConstraint* constraint = find(flag); - if (constraint != NULL && (constraint->type() <= _validating_type)) { - found = constraint; +JVMFlagConstraintChecker JVMFlagConstraintList::find_if_needs_check(const JVMFlag* flag) { + JVMFlagConstraintChecker constraint = JVMFlagConstraintList::find(flag); + if (constraint.exists() && (constraint.type() <= _validating_type)) { + return constraint; } - return found; + return JVMFlagConstraintChecker(flag, NULL); } // Check constraints for specific constraint type. @@ -299,10 +217,11 @@ bool JVMFlagConstraintList::check_constraints(JVMFlagConstraint::ConstraintType _validating_type = type; bool status = true; - for (int i=0; i<length(); i++) { - JVMFlagConstraint* constraint = at(i); - if (type != constraint->type()) continue; - if (constraint->apply(true) != JVMFlag::SUCCESS) status = false; + for (int i = 0; i < NUM_JVMFlagsEnum; i++) { + JVMFlagConstraintChecker constraint(&JVMFlag::flags[i], JVMFlagLimit::get_constraint_at(i)); + if (!constraint.exists()) continue; + if (type != constraint.type()) continue; + if (constraint.apply(true) != JVMFlag::SUCCESS) status = false; } return status; } diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp index 91a785b9434..d6119f986a2 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ #define SHARE_RUNTIME_FLAGS_JVMFLAGCONSTRAINTLIST_HPP #include "runtime/flags/jvmFlag.hpp" -#include "utilities/growableArray.hpp" +#include "runtime/flags/jvmFlagLimit.hpp" /* * Here we have a mechanism for extracting constraints (as custom functions) for flags, @@ -83,18 +83,28 @@ class JVMFlagConstraint : public CHeapObj<mtArguments> { virtual JVMFlag::Error apply_double(double value, bool verbose = true) { ShouldNotReachHere(); return JVMFlag::ERR_OTHER; }; }; +class JVMFlagConstraintChecker { + const JVMFlag* _flag; + const JVMFlagLimit* _limit; + +public: + JVMFlagConstraintChecker(const JVMFlag* flag, const JVMFlagLimit* limit) : _flag(flag), _limit(limit) {} + bool exists() const { return _limit != NULL; } + JVMFlag::Error apply(bool verbose = true) const; + + JVMFlagConstraint::ConstraintType type() const { return (JVMFlagConstraint::ConstraintType)_limit->phase(); } +#define DECLARE_CONSTRAINT_APPLY(T) JVMFlag::Error apply_ ## T(T new_value, bool verbose = true) const; + ALL_CONSTRAINT_TYPES(DECLARE_CONSTRAINT_APPLY) +}; + class JVMFlagConstraintList : public AllStatic { private: - static GrowableArray<JVMFlagConstraint*>* _constraints; // Latest constraint validation type. static JVMFlagConstraint::ConstraintType _validating_type; public: static void init(); - static int length() { return (_constraints != NULL) ? _constraints->length() : 0; } - static JVMFlagConstraint* at(int i) { return (_constraints != NULL) ? _constraints->at(i) : NULL; } - static JVMFlagConstraint* find(const JVMFlag* flag); - static JVMFlagConstraint* find_if_needs_check(const JVMFlag* flag); - static void add(JVMFlagConstraint* constraint) { _constraints->append(constraint); } + static JVMFlagConstraintChecker find(const JVMFlag* flag) { return JVMFlagConstraintChecker(flag, JVMFlagLimit::get_constraint(flag)); } + static JVMFlagConstraintChecker find_if_needs_check(const JVMFlag* flag); // True if 'AfterErgo' or later constraint functions are validated. static bool validated_after_ergo() { return _validating_type >= JVMFlagConstraint::AfterErgo; }; static bool check_constraints(JVMFlagConstraint::ConstraintType type); diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp index b63eebd410a..6b4abf8a501 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * 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,6 +26,7 @@ #define SHARE_RUNTIME_FLAGS_JVMFLAGCONSTRAINTSCOMPILER_HPP #include "runtime/flags/jvmFlag.hpp" +#include "utilities/macros.hpp" /* * Here we have compiler arguments constraints functions, which are called automatically @@ -33,46 +34,28 @@ * an appropriate error value. */ -JVMFlag::Error AliasLevelConstraintFunc(intx value, bool verbose); - -JVMFlag::Error CICompilerCountConstraintFunc(intx value, bool verbose); - -JVMFlag::Error AllocatePrefetchDistanceConstraintFunc(intx value, bool verbose); - -JVMFlag::Error AllocatePrefetchInstrConstraintFunc(intx value, bool verbose); - -JVMFlag::Error AllocatePrefetchStepSizeConstraintFunc(intx value, bool verbose); - -JVMFlag::Error CompileThresholdConstraintFunc(intx value, bool verbose); - -JVMFlag::Error OnStackReplacePercentageConstraintFunc(intx value, bool verbose); - -JVMFlag::Error CodeCacheSegmentSizeConstraintFunc(uintx value, bool verbose); - -JVMFlag::Error CompilerThreadPriorityConstraintFunc(intx value, bool verbose); - -JVMFlag::Error CodeEntryAlignmentConstraintFunc(intx value, bool verbose); - -JVMFlag::Error OptoLoopAlignmentConstraintFunc(intx value, bool verbose); - -JVMFlag::Error ArraycopyDstPrefetchDistanceConstraintFunc(uintx value, bool verbose); - -JVMFlag::Error ArraycopySrcPrefetchDistanceConstraintFunc(uintx value, bool verbose); - -JVMFlag::Error TypeProfileLevelConstraintFunc(uintx value, bool verbose); - -JVMFlag::Error InitArrayShortSizeConstraintFunc(intx value, bool verbose); - -#ifdef COMPILER2 -JVMFlag::Error InteriorEntryAlignmentConstraintFunc(intx value, bool verbose); - -JVMFlag::Error NodeLimitFudgeFactorConstraintFunc(intx value, bool verbose); -#endif - -JVMFlag::Error RTMTotalCountIncrRateConstraintFunc(int value, bool verbose); - -#ifdef COMPILER2 -JVMFlag::Error LoopStripMiningIterConstraintFunc(uintx value, bool verbose); -#endif +#define COMPILER_CONSTRAINTS(f) \ + f(intx, AliasLevelConstraintFunc) \ + f(intx, CICompilerCountConstraintFunc) \ + f(intx, AllocatePrefetchDistanceConstraintFunc) \ + f(intx, AllocatePrefetchInstrConstraintFunc) \ + f(intx, AllocatePrefetchStepSizeConstraintFunc) \ + f(intx, CompileThresholdConstraintFunc) \ + f(intx, OnStackReplacePercentageConstraintFunc) \ + f(uintx, CodeCacheSegmentSizeConstraintFunc) \ + f(intx, CodeEntryAlignmentConstraintFunc) \ + f(intx, OptoLoopAlignmentConstraintFunc) \ + f(uintx, ArraycopyDstPrefetchDistanceConstraintFunc) \ + f(uintx, ArraycopySrcPrefetchDistanceConstraintFunc) \ + f(uintx, TypeProfileLevelConstraintFunc) \ + f(intx, InitArrayShortSizeConstraintFunc) \ + f(int , RTMTotalCountIncrRateConstraintFunc) \ +COMPILER2_PRESENT( \ + f(intx, InteriorEntryAlignmentConstraintFunc) \ + f(intx, NodeLimitFudgeFactorConstraintFunc) \ + f(uintx, LoopStripMiningIterConstraintFunc) \ +) + +COMPILER_CONSTRAINTS(DECLARE_CONSTRAINT) #endif // SHARE_RUNTIME_FLAGS_JVMFLAGCONSTRAINTSCOMPILER_HPP diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index 61d58c53829..9d55a110f46 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlag.hpp" +#include "runtime/flags/jvmFlagLimit.hpp" #include "runtime/flags/jvmFlagConstraintsRuntime.hpp" #include "runtime/globals.hpp" #include "runtime/safepointMechanism.hpp" @@ -131,3 +132,32 @@ JVMFlag::Error PerfDataSamplingIntervalFunc(intx value, bool verbose) { return JVMFlag::SUCCESS; } } + +JVMFlag::Error VMPageSizeConstraintFunc(uintx value, bool verbose) { + uintx min = (uintx)os::vm_page_size(); + if (value < min) { + JVMFlag::printError(verbose, + "%s %s=" UINTX_FORMAT " is outside the allowed range [ " UINTX_FORMAT + " ... " UINTX_FORMAT " ]\n", + JVMFlagLimit::last_checked_flag()->_type, + JVMFlagLimit::last_checked_flag()->_name, + value, min, max_uintx); + return JVMFlag::VIOLATES_CONSTRAINT; + } + + return JVMFlag::SUCCESS; +} + +JVMFlag::Error NUMAInterleaveGranularityConstraintFunc(size_t value, bool verbose) { + size_t min = os::vm_allocation_granularity(); + size_t max = NOT_LP64(2*G) LP64_ONLY(8192*G); + + if (value < min || value > max) { + JVMFlag::printError(verbose, + "size_t NUMAInterleaveGranularity=" UINTX_FORMAT " is outside the allowed range [ " UINTX_FORMAT + " ... " UINTX_FORMAT " ]\n", value, min, max); + return JVMFlag::VIOLATES_CONSTRAINT; + } + + return JVMFlag::SUCCESS; +} diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp index 5e1f8d8bdf1..8bc3a9a1548 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * 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,15 +33,17 @@ * an appropriate error value. */ -JVMFlag::Error ObjectAlignmentInBytesConstraintFunc(intx value, bool verbose); - -JVMFlag::Error ContendedPaddingWidthConstraintFunc(intx value, bool verbose); - -JVMFlag::Error BiasedLockingBulkRebiasThresholdFunc(intx value, bool verbose); -JVMFlag::Error BiasedLockingStartupDelayFunc(intx value, bool verbose); -JVMFlag::Error BiasedLockingBulkRevokeThresholdFunc(intx value, bool verbose); -JVMFlag::Error BiasedLockingDecayTimeFunc(intx value, bool verbose); - -JVMFlag::Error PerfDataSamplingIntervalFunc(intx value, bool verbose); +#define RUNTIME_CONSTRAINTS(f) \ + f(intx, ObjectAlignmentInBytesConstraintFunc) \ + f(intx, ContendedPaddingWidthConstraintFunc) \ + f(intx, BiasedLockingBulkRebiasThresholdFunc) \ + f(intx, BiasedLockingStartupDelayFunc) \ + f(intx, BiasedLockingBulkRevokeThresholdFunc) \ + f(intx, BiasedLockingDecayTimeFunc) \ + f(intx, PerfDataSamplingIntervalFunc) \ + f(uintx, VMPageSizeConstraintFunc) \ + f(size_t, NUMAInterleaveGranularityConstraintFunc) + +RUNTIME_CONSTRAINTS(DECLARE_CONSTRAINT) #endif // SHARE_RUNTIME_FLAGS_JVMFLAGCONSTRAINTSRUNTIME_HPP diff --git a/src/hotspot/share/runtime/flags/jvmFlagLimit.cpp b/src/hotspot/share/runtime/flags/jvmFlagLimit.cpp new file mode 100644 index 00000000000..b9d5ae5a8e9 --- /dev/null +++ b/src/hotspot/share/runtime/flags/jvmFlagLimit.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "gc/shared/jvmFlagConstraintsGC.hpp" +#include "runtime/flags/jvmFlag.hpp" +#include "runtime/flags/jvmFlagLimit.hpp" +#include "runtime/flags/jvmFlagConstraintList.hpp" +#include "runtime/flags/jvmFlagConstraintsCompiler.hpp" +#include "runtime/flags/jvmFlagConstraintsRuntime.hpp" +#include "runtime/flags/jvmFlagRangeList.hpp" +#include "runtime/globals_extension.hpp" +#include "gc/shared/referenceProcessor.hpp" +#include "oops/markWord.hpp" +#include "runtime/task.hpp" + +//---------------------------------------------------------------------- +// Build flagLimitTable[] + +#define CONSTRAINT_ENUM(func) constraint_enum_ ## func +#define CONSTRAINT_ENUM_(type, func) CONSTRAINT_ENUM(func), +#define CONSTRAINT_FUNC(type, func) (void*)&func, + +enum JVMFlagConstraintsEnum : int { + ALL_CONSTRAINTS(CONSTRAINT_ENUM_) + NUM_JVMFlagConstraintsEnum +}; + +static void* const flagConstraintTable[NUM_JVMFlagConstraintsEnum] = { + ALL_CONSTRAINTS(CONSTRAINT_FUNC) +}; + +void* JVMFlagLimit::constraint_func() const { + int i = _constraint_func; + assert(0 <= i && i < NUM_JVMFlagConstraintsEnum, "sanity"); + return flagConstraintTable[i]; +} + +struct DummyLimit { + char dummy; + constexpr DummyLimit(...) : dummy() {} +}; + +template <typename T> +class LimitGetter { +public: + // These functions return NULL for develop flags in a PRODUCT build + static constexpr const JVMFlagLimit* no_limit(...) { + return NULL; + } + + // This is for flags that have neither range no constraint. We don't need the JVMFlagLimit struct. + static constexpr const JVMFlagLimit* get_limit(const JVMTypedFlagLimit<T>* p, int dummy) { + return NULL; + } + + static constexpr const JVMFlagLimit* get_limit(const JVMTypedFlagLimit<T>* p, int dummy, T min, T max) { + return p; + } + static constexpr const JVMFlagLimit* get_limit(const JVMTypedFlagLimit<T>* p, int dummy, ConstraintMarker dummy2, short func, int phase) { + return p; + } + static constexpr const JVMFlagLimit* get_limit(const JVMTypedFlagLimit<T>* p, int dummy, T min, T max, ConstraintMarker dummy2, short func, int phase) { + return p; + } + static constexpr const JVMFlagLimit* get_limit(const JVMTypedFlagLimit<T>* p, int dummy, ConstraintMarker dummy2, short func, int phase, T min, T max) { + return p; + } +}; + +// macro body starts here -------------------+ +// | +// v +#define FLAG_LIMIT_DEFINE( type, name, ...) ); constexpr JVMTypedFlagLimit<type> limit_##name(0 +#define FLAG_LIMIT_DEFINE_DUMMY(type, name, ...) ); constexpr DummyLimit nolimit_##name(0 +#define FLAG_LIMIT_PTR( type, name, ...) ), LimitGetter<type>::get_limit(&limit_##name, 0 +#define FLAG_LIMIT_PTR_NONE( type, name, ...) ), LimitGetter<type>::no_limit(0 +#define APPLY_FLAG_RANGE(...) , __VA_ARGS__ +#define APPLY_FLAG_CONSTRAINT(func, phase) , next_two_args_are_constraint, (short)CONSTRAINT_ENUM(func), int(JVMFlagConstraint::phase) + +constexpr JVMTypedFlagLimit<int> limit_dummy +( +#ifdef PRODUCT + ALL_FLAGS(FLAG_LIMIT_DEFINE_DUMMY, + FLAG_LIMIT_DEFINE_DUMMY, + FLAG_LIMIT_DEFINE, + FLAG_LIMIT_DEFINE, + FLAG_LIMIT_DEFINE_DUMMY, + APPLY_FLAG_RANGE, + APPLY_FLAG_CONSTRAINT) +#else + ALL_FLAGS(FLAG_LIMIT_DEFINE, + FLAG_LIMIT_DEFINE, + FLAG_LIMIT_DEFINE, + FLAG_LIMIT_DEFINE, + FLAG_LIMIT_DEFINE, + APPLY_FLAG_RANGE, + APPLY_FLAG_CONSTRAINT) +#endif +); + +static constexpr const JVMFlagLimit* const flagLimitTable[1 + NUM_JVMFlagsEnum] = { + // Because FLAG_LIMIT_PTR must start with an "),", we have to place a dummy element here. + LimitGetter<int>::get_limit(NULL, 0 + +#ifdef PRODUCT + ALL_FLAGS(FLAG_LIMIT_PTR_NONE, + FLAG_LIMIT_PTR_NONE, + FLAG_LIMIT_PTR, + FLAG_LIMIT_PTR, + FLAG_LIMIT_PTR_NONE, + APPLY_FLAG_RANGE, + APPLY_FLAG_CONSTRAINT) +#else + ALL_FLAGS(FLAG_LIMIT_PTR, + FLAG_LIMIT_PTR, + FLAG_LIMIT_PTR, + FLAG_LIMIT_PTR, + FLAG_LIMIT_PTR, + APPLY_FLAG_RANGE, + APPLY_FLAG_CONSTRAINT) +#endif + ) +}; + +int JVMFlagLimit::_last_checked = -1; + +const JVMFlagLimit* const* JVMFlagLimit::flagLimits = &flagLimitTable[1]; // excludes dummy diff --git a/src/hotspot/share/runtime/flags/jvmFlagLimit.hpp b/src/hotspot/share/runtime/flags/jvmFlagLimit.hpp new file mode 100644 index 00000000000..4474b15963d --- /dev/null +++ b/src/hotspot/share/runtime/flags/jvmFlagLimit.hpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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_RUNTIME_FLAGS_JVMFLAGLIMIT_HPP +#define SHARE_RUNTIME_FLAGS_JVMFLAGLIMIT_HPP + +#include "runtime/flags/jvmFlag.hpp" + +#define ALL_LIMIT_TYPES(f) \ + f(int) \ + f(intx) \ + f(uint) \ + f(uintx) \ + f(uint64_t) \ + f(size_t) \ + f(double) + +#define ALL_RANGE_TYPES(f) ALL_LIMIT_TYPES(f) +#define ALL_CONSTRAINT_TYPES(f) ALL_LIMIT_TYPES(f) f(bool) + +template <typename T> class JVMTypedFlagLimit; + + +// A JVMFlagLimit is created for each JVMFlag that has a range() and/or constraint() in its declaration in +// the globals_xxx.hpp file. +// +// To query the range information of a JVMFlag: +// JVMFlagLimit::get_range(JVMFlag*) +// JVMFlagLimit::get_range_at(int flag_enum) +// If the given flag doesn't have a range, NULL is returned. +// +// To query the constraint information of a JVMFlag: +// JVMFlagLimit::get_constraint(JVMFlag*) +// JVMFlagLimit::get_constraint_at(int flag_enum) +// If the given flag doesn't have a constraint, NULL is returned. + +class JVMFlagLimit { + short _constraint_func; + char _phase; + char _kind; + + static const JVMFlagLimit* const* flagLimits; + static int _last_checked; + +protected: + static constexpr int HAS_RANGE = 1; + static constexpr int HAS_CONSTRAINT = 2; + +private: + static const JVMFlagLimit* get_kind_at(int flag_enum, int required_kind) { + const JVMFlagLimit* limit = at(flag_enum); + if (limit != NULL && (limit->_kind & required_kind) != 0) { + _last_checked = flag_enum; + return limit; + } else { + return NULL; + } + } + + static const JVMFlagLimit* at(int flag_enum) { + JVMFlag::assert_valid_flag_enum(flag_enum); + return flagLimits[flag_enum]; + } + +public: + void* constraint_func() const; + char phase() const { return _phase; } + char kind() const { return _kind; } + + constexpr JVMFlagLimit(short func, short phase, short kind) : _constraint_func(func), _phase(phase), _kind(kind) {} + + static const JVMFlagLimit* get_range(const JVMFlag* flag) { + return get_range_at(flag->flag_enum()); + } + static const JVMFlagLimit* get_range_at(int flag_enum) { + return get_kind_at(flag_enum, HAS_RANGE); + } + + static const JVMFlagLimit* get_constraint(const JVMFlag* flag) { + return get_constraint_at(flag->flag_enum()); + } + static const JVMFlagLimit* get_constraint_at(int flag_enum) { + return get_kind_at(flag_enum, HAS_CONSTRAINT); + } + + static const JVMFlag* last_checked_flag() { + if (_last_checked >= 0) { + return JVMFlag::flag_from_enum(_last_checked); + } else { + return NULL; + } + } + +#define AS_TYPED_LIMIT(type) inline JVMTypedFlagLimit<type>* as_ ## type() const { return (JVMTypedFlagLimit<type>*)this; } + ALL_RANGE_TYPES(AS_TYPED_LIMIT) + +}; + +enum ConstraintMarker { + next_two_args_are_constraint, +}; + +template <typename T> +class JVMTypedFlagLimit : public JVMFlagLimit { + const T _min; + const T _max; + +public: + // dummy - no range or constraint. This object will not be emitted into the .o file + // because we declare it as "const" but has no reference to it. + constexpr JVMTypedFlagLimit(int dummy) : + JVMFlagLimit(0, 0, 0), _min(0), _max(0) {} + + // range only + constexpr JVMTypedFlagLimit(int dummy, T min, T max) : + JVMFlagLimit(0, 0, HAS_RANGE), _min(min), _max(max) {} + + // constraint only + constexpr JVMTypedFlagLimit(int dummy, ConstraintMarker dummy2, short func, int phase) : + JVMFlagLimit(func, phase, HAS_CONSTRAINT), _min(0), _max(0) {} + + // range and constraint + constexpr JVMTypedFlagLimit(int dummy, T min, T max, ConstraintMarker dummy2, short func, int phase) : + JVMFlagLimit(func, phase, HAS_RANGE | HAS_CONSTRAINT), _min(min), _max(max) {} + + // constraint and range + constexpr JVMTypedFlagLimit(int dummy, ConstraintMarker dummy2, short func, int phase, T min, T max) : + JVMFlagLimit(func, phase, HAS_RANGE | HAS_CONSTRAINT), _min(min), _max(max) {} + + T min() const { return _min; } + T max() const { return _max; } +}; + +#endif // SHARE_RUNTIME_FLAGS_JVMFLAGLIMIT_HPP diff --git a/src/hotspot/share/runtime/flags/jvmFlagLookup.cpp b/src/hotspot/share/runtime/flags/jvmFlagLookup.cpp new file mode 100644 index 00000000000..e8d57967251 --- /dev/null +++ b/src/hotspot/share/runtime/flags/jvmFlagLookup.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/flags/jvmFlag.hpp" +#include "runtime/flags/jvmFlagLookup.hpp" +#include "utilities/defaultStream.hpp" + +#define DO_FLAG(type, name,...) DO_HASH(FLAG_MEMBER_ENUM(name), XSTR(name)) + +#define DO_HASH(flag_enum, flag_name) { \ + u2 hash = hash_code(flag_name); \ + int bucket_index = (int)(hash % NUM_BUCKETS); \ + _hashes[flag_enum] = hash; \ + _table[flag_enum] = _buckets[bucket_index]; \ + _buckets[bucket_index] = (short)flag_enum; \ +} + +constexpr JVMFlagLookup::JVMFlagLookup() : _buckets(), _table(), _hashes() { + for (int i = 0; i < NUM_BUCKETS; i++) { + _buckets[i] = -1; + } + + ALL_FLAGS(DO_FLAG, + DO_FLAG, + DO_FLAG, + DO_FLAG, + DO_FLAG, + IGNORE_RANGE, + IGNORE_CONSTRAINT) +} + +constexpr JVMFlagLookup _flag_lookup_table; + +JVMFlag* JVMFlagLookup::find_impl(const char* name, size_t length) const { + u2 hash = hash_code(name, length); + int bucket_index = (int)(hash % NUM_BUCKETS); + for (int flag_enum = _buckets[bucket_index]; flag_enum >= 0; ) { + if (_hashes[flag_enum] == hash) { + JVMFlag* flag = JVMFlag::flags + flag_enum; + if (strncmp(name, flag->_name, length) == 0) { + // We know flag->_name has at least <length> bytes. + // Make sure it has exactly <length> bytes + if (flag->_name[length] == 0) { + return flag; + } + } + } + flag_enum = (int)_table[flag_enum]; + } + + return NULL; +} + +JVMFlag* JVMFlagLookup::find(const char* name, size_t length) { + return _flag_lookup_table.find_impl(name, length); +} diff --git a/src/hotspot/share/runtime/flags/jvmFlagLookup.hpp b/src/hotspot/share/runtime/flags/jvmFlagLookup.hpp new file mode 100644 index 00000000000..3ac31b0e61e --- /dev/null +++ b/src/hotspot/share/runtime/flags/jvmFlagLookup.hpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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_RUNTIME_FLAGS_JVMFLAGLOOKUP_HPP +#define SHARE_RUNTIME_FLAGS_JVMFLAGLOOKUP_HPP + +#include "runtime/globals_extension.hpp" +#include "runtime/flags/jvmFlag.hpp" + +// This is a hashtable that maps from (const char*) to (JVMFlag*) to speed up +// the processing of JVM command-line arguments at runtime. +// +// With constexpr, this table is generated at C++ compile time so there's +// no set up cost at runtime. +class JVMFlagLookup { + static constexpr int NUM_BUCKETS = 277; + short _buckets[NUM_BUCKETS]; + short _table[NUM_JVMFlagsEnum]; + u2 _hashes[NUM_JVMFlagsEnum]; + + // Cannot use strlen() -- it's not constexpr. + static constexpr size_t string_len(const char* s) { + size_t len = 0; + while (*s != 0) { + len++; + s++; + } + return len; + } + + // This is executed at build-time only, so it doesn't matter if we walk + // the string twice. + static constexpr u2 hash_code(const char* s) { + return hash_code(s, string_len(s)); + } + + static constexpr u2 hash_code(const char* s, size_t len) { + u2 h = 0; + while (len -- > 0) { + h = (u2)(31*h + (u2) *s); + s++; + } + return h; + } + + JVMFlag* find_impl(const char* flag_name, size_t length) const; + +public: + constexpr JVMFlagLookup(); + static JVMFlag* find(const char* flag_name, size_t length); +}; + +#endif // SHARE_RUNTIME_FLAGS_JVMFLAGLOOKUP_HPP diff --git a/src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp b/src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp index 1751a92056f..f79f7ec47f8 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp @@ -31,6 +31,7 @@ #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlag.hpp" #include "runtime/flags/jvmFlagConstraintList.hpp" +#include "runtime/flags/jvmFlagConstraintsRuntime.hpp" #include "runtime/flags/jvmFlagRangeList.hpp" #include "runtime/globals.hpp" #include "runtime/globals_extension.hpp" @@ -241,122 +242,69 @@ class JVMFlagRange_double : public JVMFlagRange { } }; -// No constraint emitting -void emit_range_no(...) { /* NOP */ } - -// No constraint emitting if function argument is NOT provided -void emit_range_bool(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_ccstr(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_ccstrlist(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_int(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_intx(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_uint(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_uintx(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_uint64_t(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_size_t(const JVMFlag* /*flag*/) { /* NOP */ } -void emit_range_double(const JVMFlag* /*flag*/) { /* NOP */ } - -// JVMFlagRange emitting code functions if range arguments are provided -void emit_range_int(const JVMFlag* flag, int min, int max) { - JVMFlagRangeList::add(new JVMFlagRange_int(flag, min, max)); -} -void emit_range_intx(const JVMFlag* flag, intx min, intx max) { - JVMFlagRangeList::add(new JVMFlagRange_intx(flag, min, max)); -} -void emit_range_uint(const JVMFlag* flag, uint min, uint max) { - JVMFlagRangeList::add(new JVMFlagRange_uint(flag, min, max)); -} -void emit_range_uintx(const JVMFlag* flag, uintx min, uintx max) { - JVMFlagRangeList::add(new JVMFlagRange_uintx(flag, min, max)); -} -void emit_range_uint64_t(const JVMFlag* flag, uint64_t min, uint64_t max) { - JVMFlagRangeList::add(new JVMFlagRange_uint64_t(flag, min, max)); -} -void emit_range_size_t(const JVMFlag* flag, size_t min, size_t max) { - JVMFlagRangeList::add(new JVMFlagRange_size_t(flag, min, max)); -} -void emit_range_double(const JVMFlag* flag, double min, double max) { - JVMFlagRangeList::add(new JVMFlagRange_double(flag, min, max)); +#define DEFINE_RANGE_CHECK(T) \ +JVMFlag::Error JVMFlagRangeChecker::check_ ## T(T value, bool verbose) const { \ + assert(exists(), "must be"); \ + JVMFlagRange_ ## T range(_flag, _limit->as_ ## T()->min(), _limit->as_ ## T()->max()); \ + return range.check_ ## T(value, verbose); \ } -// Generate code to call emit_range_xxx function -#define EMIT_RANGE_START (void)(0 -#define EMIT_RANGE(type, name) ); emit_range_##type(JVMFlagEx::flag_from_enum(FLAG_MEMBER_ENUM(name)) -#define EMIT_RANGE_NO ); emit_range_no(0 -#define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_PD_DIAGNOSTIC_FLAG(type, name, doc) EMIT_RANGE(type, name) -#ifndef PRODUCT -#define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc) EMIT_RANGE(type, name) -#define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#else -#define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc) EMIT_RANGE_NO -#define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc) EMIT_RANGE_NO -#define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc) EMIT_RANGE_NO -#endif -#ifdef _LP64 -#define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_RANGE(type, name) -#else -#define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_RANGE_NO -#endif -#define EMIT_RANGE_END ); - -// Generate func argument to pass into emit_range_xxx functions -#define EMIT_RANGE_CHECK(a, b) , a, b - -#define INITIAL_RANGES_SIZE 379 -GrowableArray<JVMFlagRange*>* JVMFlagRangeList::_ranges = NULL; - -// Check the ranges of all flags that have them -void JVMFlagRangeList::init(void) { - - _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<JVMFlagRange*>(INITIAL_RANGES_SIZE, mtArguments); - - EMIT_RANGE_START - - ALL_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, - EMIT_RANGE_PD_DEVELOPER_FLAG, - EMIT_RANGE_PRODUCT_FLAG, - EMIT_RANGE_PD_PRODUCT_FLAG, - EMIT_RANGE_DIAGNOSTIC_FLAG, - EMIT_RANGE_PD_DIAGNOSTIC_FLAG, - EMIT_RANGE_EXPERIMENTAL_FLAG, - EMIT_RANGE_NOTPRODUCT_FLAG, - EMIT_RANGE_MANAGEABLE_FLAG, - EMIT_RANGE_PRODUCT_RW_FLAG, - EMIT_RANGE_LP64_PRODUCT_FLAG, - EMIT_RANGE_CHECK, - IGNORE_CONSTRAINT) - - EMIT_RANGE_END +ALL_RANGE_TYPES(DEFINE_RANGE_CHECK) + + +JVMFlag::Error JVMFlagRangeChecker::check(bool verbose) const { +#define CHECK_RANGE(T) \ + if (_flag->is_ ## T()) { \ + JVMFlagRange_ ## T range(_flag, _limit->as_ ## T()->min(), _limit->as_ ## T()->max()); \ + return range.check(verbose); \ + } + + ALL_RANGE_TYPES(CHECK_RANGE); + + ShouldNotReachHere(); + return JVMFlag::INVALID_FLAG; } -JVMFlagRange* JVMFlagRangeList::find(const JVMFlag* flag) { - JVMFlagRange* found = NULL; - for (int i=0; i<length(); i++) { - JVMFlagRange* range = at(i); - if (range->flag() == flag) { - found = range; - break; - } +void JVMFlagRangeChecker::print(outputStream* out) const { +#define PRINT_RANGE(T) \ + if (_flag->is_ ## T()) { \ + JVMFlagRange_ ## T range(_flag, _limit->as_ ## T()->min(), _limit->as_ ## T()->max()); \ + range.print(out); \ + return; \ } - return found; + + ALL_RANGE_TYPES(PRINT_RANGE); + + ShouldNotReachHere(); } void JVMFlagRangeList::print(outputStream* st, const JVMFlag* flag, RangeStrFunc default_range_str_func) { - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { - range->print(st); + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { + range.print(st); } else { - JVMFlagConstraint* constraint = JVMFlagConstraintList::find(flag); - if (constraint != NULL) { - assert(default_range_str_func!=NULL, "default_range_str_func must be provided"); - st->print("%s", default_range_str_func()); + const JVMFlagLimit* limit = JVMFlagLimit::get_constraint(flag); + if (limit != NULL) { + void* func = limit->constraint_func(); + + // Two special cases where the lower limit of the range is defined by an os:: function call + // and cannot be initialized at compile time with constexpr. + if (func == (void*)VMPageSizeConstraintFunc) { + uintx min = (uintx)os::vm_page_size(); + uintx max = max_uintx; + + JVMFlagRange_uintx tmp(flag, min, max); + tmp.print(st); + } else if (func == (void*)NUMAInterleaveGranularityConstraintFunc) { + size_t min = os::vm_allocation_granularity(); + size_t max = NOT_LP64(2*G) LP64_ONLY(8192*G); + + JVMFlagRange_size_t tmp(flag, min, max); + tmp.print(st); + } else { + assert(default_range_str_func!=NULL, "default_range_str_func must be provided"); + st->print("%s", default_range_str_func()); + } } else { st->print("[ ... ]"); } @@ -365,9 +313,9 @@ void JVMFlagRangeList::print(outputStream* st, const JVMFlag* flag, RangeStrFunc bool JVMFlagRangeList::check_ranges() { bool status = true; - for (int i=0; i<length(); i++) { - JVMFlagRange* range = at(i); - if (range->check(true) != JVMFlag::SUCCESS) status = false; + for (int i = 0; i < NUM_JVMFlagsEnum; i++) { + JVMFlagRangeChecker range(&JVMFlag::flags[i], JVMFlagLimit::get_range_at(i)); + if (range.exists() && range.check(true) != JVMFlag::SUCCESS) status = false; } return status; } diff --git a/src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp b/src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp index 0219f2fad94..ecc30842126 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ #define SHARE_RUNTIME_FLAGS_JVMFLAGRANGELIST_HPP #include "runtime/flags/jvmFlag.hpp" -#include "utilities/growableArray.hpp" +#include "runtime/flags/jvmFlagLimit.hpp" /* * Here we have a mechanism for extracting ranges specified in flag macro tables. @@ -58,14 +58,23 @@ class JVMFlagRange : public CHeapObj<mtArguments> { virtual void print(outputStream* st) { ; } }; +class JVMFlagRangeChecker { + const JVMFlag* _flag; + const JVMFlagLimit* _limit; + +public: + JVMFlagRangeChecker(const JVMFlag* flag, const JVMFlagLimit* limit) : _flag(flag), _limit(limit) {} + bool exists() const { return _limit != NULL; } + JVMFlag::Error check(bool verbose = true) const; + void print(outputStream* st) const; + +#define DECLARE_RANGE_CHECK(T) JVMFlag::Error check_ ## T(T new_value, bool verbose = true) const; + ALL_RANGE_TYPES(DECLARE_RANGE_CHECK) +}; + class JVMFlagRangeList : public AllStatic { - static GrowableArray<JVMFlagRange*>* _ranges; public: - static void init(); - static int length() { return (_ranges != NULL) ? _ranges->length() : 0; } - static JVMFlagRange* at(int i) { return (_ranges != NULL) ? _ranges->at(i) : NULL; } - static JVMFlagRange* find(const JVMFlag* flag); - static void add(JVMFlagRange* range) { _ranges->append(range); } + static JVMFlagRangeChecker find(const JVMFlag* flag) { return JVMFlagRangeChecker(flag, JVMFlagLimit::get_range(flag)); } static void print(outputStream* st, const JVMFlag* flag, RangeStrFunc default_range_str_func); // Check the final values of all flags for ranges. static bool check_ranges(); diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 01b0e641cb1..f076b558d5d 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -672,13 +672,13 @@ void frame::print_on_error(outputStream* st, char* buf, int buflen, bool verbose */ class InterpreterFrameClosure : public OffsetClosure { private: - frame* _fr; - OopClosure* _f; - int _max_locals; - int _max_stack; + const frame* _fr; + OopClosure* _f; + int _max_locals; + int _max_stack; public: - InterpreterFrameClosure(frame* fr, int max_locals, int max_stack, + InterpreterFrameClosure(const frame* fr, int max_locals, int max_stack, OopClosure* f) { _fr = fr; _max_locals = max_locals; @@ -709,16 +709,15 @@ class InterpreterFrameClosure : public OffsetClosure { } int max_locals() { return _max_locals; } - frame* fr() { return _fr; } }; class InterpretedArgumentOopFinder: public SignatureIterator { private: - OopClosure* _f; // Closure to invoke - int _offset; // TOS-relative offset, decremented with each argument - bool _has_receiver; // true if the callee has a receiver - frame* _fr; + OopClosure* _f; // Closure to invoke + int _offset; // TOS-relative offset, decremented with each argument + bool _has_receiver; // true if the callee has a receiver + const frame* _fr; friend class SignatureIterator; // so do_parameters_on can call do_type void do_type(BasicType type) { @@ -733,7 +732,7 @@ class InterpretedArgumentOopFinder: public SignatureIterator { } public: - InterpretedArgumentOopFinder(Symbol* signature, bool has_receiver, frame* fr, OopClosure* f) : SignatureIterator(signature), _has_receiver(has_receiver) { + InterpretedArgumentOopFinder(Symbol* signature, bool has_receiver, const frame* fr, OopClosure* f) : SignatureIterator(signature), _has_receiver(has_receiver) { // compute size of arguments int args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); assert(!fr->is_interpreted_frame() || @@ -769,10 +768,10 @@ class InterpretedArgumentOopFinder: public SignatureIterator { // visits and GC's all the arguments in entry frame class EntryFrameOopFinder: public SignatureIterator { private: - bool _is_static; - int _offset; - frame* _fr; - OopClosure* _f; + bool _is_static; + int _offset; + const frame* _fr; + OopClosure* _f; friend class SignatureIterator; // so do_parameters_on can call do_type void do_type(BasicType type) { @@ -789,7 +788,7 @@ class EntryFrameOopFinder: public SignatureIterator { } public: - EntryFrameOopFinder(frame* frame, Symbol* signature, bool is_static) : SignatureIterator(signature) { + EntryFrameOopFinder(const frame* frame, Symbol* signature, bool is_static) : SignatureIterator(signature) { _f = NULL; // will be set later _fr = frame; _is_static = is_static; @@ -811,7 +810,7 @@ oop* frame::interpreter_callee_receiver_addr(Symbol* signature) { } -void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache) { +void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache) const { assert(is_interpreted_frame(), "Not an interpreted frame"); assert(map != NULL, "map must be set"); Thread *thread = Thread::current(); @@ -892,12 +891,12 @@ void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool quer } -void frame::oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) { +void frame::oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) const { InterpretedArgumentOopFinder finder(signature, has_receiver, this, f); finder.oops_do(); } -void frame::oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* reg_map) { +void frame::oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* reg_map) const { assert(_cb != NULL, "sanity check"); if (_cb->oop_maps() != NULL) { OopMapSet::oops_do(this, reg_map, f); @@ -974,7 +973,7 @@ class CompiledArgumentOopFinder: public SignatureIterator { }; void frame::oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix, - const RegisterMap* reg_map, OopClosure* f) { + const RegisterMap* reg_map, OopClosure* f) const { ResourceMark rm; CompiledArgumentOopFinder finder(signature, has_receiver, has_appendix, f, *this, reg_map); finder.oops_do(); @@ -1023,7 +1022,7 @@ oop frame::get_native_receiver() { return owner; } -void frame::oops_entry_do(OopClosure* f, const RegisterMap* map) { +void frame::oops_entry_do(OopClosure* f, const RegisterMap* map) const { assert(map != NULL, "map must be set"); if (map->include_argument_oops()) { // must collect argument oops, as nobody else is doing it @@ -1037,7 +1036,7 @@ void frame::oops_entry_do(OopClosure* f, const RegisterMap* map) { } -void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) { +void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map, bool use_interpreter_oop_map_cache) const { #ifndef PRODUCT // simulate GC crash here to dump java thread in error report if (CrashGCForDumpingJavaThread) { @@ -1056,7 +1055,7 @@ void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* ma } } -void frame::nmethods_do(CodeBlobClosure* cf) { +void frame::nmethods_do(CodeBlobClosure* cf) const { if (_cb != NULL && _cb->is_nmethod()) { cf->do_code_blob(_cb); } @@ -1064,7 +1063,7 @@ void frame::nmethods_do(CodeBlobClosure* cf) { // Call f closure on the interpreted Method*s in the stack. -void frame::metadata_do(MetadataClosure* f) { +void frame::metadata_do(MetadataClosure* f) const { ResourceMark rm; if (is_interpreted_frame()) { Method* m = this->interpreter_frame_method(); @@ -1073,7 +1072,7 @@ void frame::metadata_do(MetadataClosure* f) { } } -void frame::verify(const RegisterMap* map) { +void frame::verify(const RegisterMap* map) const { // for now make sure receiver type is correct if (is_interpreted_frame()) { Method* method = interpreter_frame_method(); @@ -1087,7 +1086,7 @@ void frame::verify(const RegisterMap* map) { #if COMPILER2_OR_JVMCI assert(DerivedPointerTable::is_empty(), "must be empty before verify"); #endif - oops_do_internal(&VerifyOopClosure::verify_oop, NULL, (RegisterMap*)map, false); + oops_do_internal(&VerifyOopClosure::verify_oop, NULL, map, false); } diff --git a/src/hotspot/share/runtime/frame.hpp b/src/hotspot/share/runtime/frame.hpp index 5dfe01d3ffa..fec45c5c11d 100644 --- a/src/hotspot/share/runtime/frame.hpp +++ b/src/hotspot/share/runtime/frame.hpp @@ -359,27 +359,27 @@ class frame { oop* oopmapreg_to_location(VMReg reg, const RegisterMap* reg_map) const; // Oops-do's - void oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix, const RegisterMap* reg_map, OopClosure* f); - void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true); + void oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix, const RegisterMap* reg_map, OopClosure* f) const; + void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true) const; private: - void oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f); + void oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) const; // Iteration of oops - void oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache); - void oops_entry_do(OopClosure* f, const RegisterMap* map); - void oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map); + void oops_do_internal(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map, bool use_interpreter_oop_map_cache) const; + void oops_entry_do(OopClosure* f, const RegisterMap* map) const; + void oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map) const; int adjust_offset(Method* method, int index); // helper for above fn public: // Memory management - void oops_do(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cf, map, true); } - void nmethods_do(CodeBlobClosure* cf); + void oops_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map) const { oops_do_internal(f, cf, map, true); } + void nmethods_do(CodeBlobClosure* cf) const; // RedefineClasses support for finding live interpreted methods on the stack - void metadata_do(MetadataClosure* f); + void metadata_do(MetadataClosure* f) const; // Verification - void verify(const RegisterMap* map); + void verify(const RegisterMap* map) const; static bool verify_return_pc(address x); // Usage: // assert(frame::verify_return_pc(return_address), "must be a return pc"); diff --git a/src/hotspot/share/runtime/globals.cpp b/src/hotspot/share/runtime/globals.cpp index 0a95d95f21e..0371fd72f9f 100644 --- a/src/hotspot/share/runtime/globals.cpp +++ b/src/hotspot/share/runtime/globals.cpp @@ -40,39 +40,22 @@ #include "utilities/stringUtils.hpp" // Implementation macros -#define MATERIALIZE_PRODUCT_FLAG(type, name, value, doc) type name = value; -#define MATERIALIZE_PD_PRODUCT_FLAG(type, name, doc) type name = pd_##name; -#define MATERIALIZE_DIAGNOSTIC_FLAG(type, name, value, doc) type name = value; -#define MATERIALIZE_PD_DIAGNOSTIC_FLAG(type, name, doc) type name = pd_##name; -#define MATERIALIZE_EXPERIMENTAL_FLAG(type, name, value, doc) type name = value; -#define MATERIALIZE_MANAGEABLE_FLAG(type, name, value, doc) type name = value; -#define MATERIALIZE_PRODUCT_RW_FLAG(type, name, value, doc) type name = value; +#define MATERIALIZE_PRODUCT_FLAG(type, name, value, ...) type name = value; +#define MATERIALIZE_PD_PRODUCT_FLAG(type, name, ...) type name = pd_##name; #ifdef PRODUCT -#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, doc) -#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc) -#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc) +#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, ...) +#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, ...) +#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, ...) #else -#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, doc) type name = value; -#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc) type name = pd_##name; -#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc) type name = value; +#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, ...) type name = value; +#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, ...) type name = pd_##name; +#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, ...) type name = value; #endif // PRODUCT -#ifdef _LP64 -#define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) type name = value; -#else -#define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) /* flag is constant */ -#endif // _LP64 - -ALL_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \ - MATERIALIZE_PD_DEVELOPER_FLAG, \ - MATERIALIZE_PRODUCT_FLAG, \ - MATERIALIZE_PD_PRODUCT_FLAG, \ - MATERIALIZE_DIAGNOSTIC_FLAG, \ - MATERIALIZE_PD_DIAGNOSTIC_FLAG, \ - MATERIALIZE_EXPERIMENTAL_FLAG, \ - MATERIALIZE_NOTPRODUCT_FLAG, \ - MATERIALIZE_MANAGEABLE_FLAG, \ - MATERIALIZE_PRODUCT_RW_FLAG, \ - MATERIALIZE_LP64_PRODUCT_FLAG, \ - IGNORE_RANGE, \ +ALL_FLAGS(MATERIALIZE_DEVELOPER_FLAG, + MATERIALIZE_PD_DEVELOPER_FLAG, + MATERIALIZE_PRODUCT_FLAG, + MATERIALIZE_PD_PRODUCT_FLAG, + MATERIALIZE_NOTPRODUCT_FLAG, + IGNORE_RANGE, IGNORE_CONSTRAINT) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 8ff669a408c..3c7c1df67af 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -38,23 +38,37 @@ // develop flags are settable / visible only during development and are constant in the PRODUCT version // product flags are always settable / visible // notproduct flags are settable / visible only during development and are not declared in the PRODUCT version +// develop_pd/product_pd flags are the same as develop/product, except that their default values +// are specified in platform-dependent header files. + +// Flags must be declared with the following number of parameters: +// non-pd flags: +// (type, name, default_value, doc), or +// (type, name, default_value, extra_attrs, doc) +// pd flags: +// (type, name, doc), or +// (type, name, extra_attrs, doc) // A flag must be declared with one of the following types: // bool, int, uint, intx, uintx, size_t, ccstr, ccstrlist, double, or uint64_t. // The type "ccstr" and "ccstrlist" are an alias for "const char*" and is used // only in this file, because the macrology requires single-token type names. -// Note: Diagnostic options not meant for VM tuning or for product modes. -// They are to be used for VM quality assurance or field diagnosis -// of VM bugs. They are hidden so that users will not be encouraged to -// try them as if they were VM ordinary execution options. However, they -// are available in the product version of the VM. Under instruction -// from support engineers, VM customers can turn them on to collect -// diagnostic information about VM problems. To use a VM diagnostic -// option, you must first specify +UnlockDiagnosticVMOptions. -// (This master switch also affects the behavior of -Xprintflags.) +// The optional extra_attrs parameter may have one of the following values: +// DIAGNOSTIC, EXPERIMENTAL, or MANAGEABLE. Currently extra_attrs can be used +// only with product/product_pd flags. +// +// DIAGNOSTIC options are not meant for VM tuning or for product modes. +// They are to be used for VM quality assurance or field diagnosis +// of VM bugs. They are hidden so that users will not be encouraged to +// try them as if they were VM ordinary execution options. However, they +// are available in the product version of the VM. Under instruction +// from support engineers, VM customers can turn them on to collect +// diagnostic information about VM problems. To use a VM diagnostic +// option, you must first specify +UnlockDiagnosticVMOptions. +// (This master switch also affects the behavior of -Xprintflags.) // -// experimental flags are in support of features that are not +// EXPERIMENTAL flags are in support of features that are not // part of the officially supported product, but are available // for experimenting with. They could, for example, be performance // features that may not have undergone full or rigorous QA, but which may @@ -70,7 +84,7 @@ // and they are not supported on production loads, except under explicit // direction from support engineers. // -// manageable flags are writeable external product flags. +// MANAGEABLE flags are writeable external product flags. // They are dynamically writeable through the JDK management interface // (com.sun.management.HotSpotDiagnosticMXBean API) and also through JConsole. // These flags are external exported interface (see CCC). The list of @@ -84,20 +98,7 @@ // and not reuse state related to the flag state at any given time. // - you want the flag to be queried programmatically by the customers. // -// product_rw flags are writeable internal product flags. -// They are like "manageable" flags but for internal/private use. -// The list of product_rw flags are internal/private flags which -// may be changed/removed in a future release. It can be set -// through the management interface to get/set value -// when the name of flag is supplied. -// -// A flag can be made as "product_rw" only if -// - the VM implementation supports dynamic setting of the flag. -// This implies that the VM must *always* query the flag variable -// and not reuse state related to the flag state at any given time. -// -// Note that when there is a need to support develop flags to be writeable, -// it can be done in the same way as product_rw. + // // range is a macro that will expand to min and max arguments for range // checking code if provided - see jvmFlagRangeList.hpp @@ -112,28 +113,52 @@ const size_t minimumStringTableSize = 128; const size_t defaultSymbolTableSize = 32768; // 2^15 const size_t minimumSymbolTableSize = 1024; -#define RUNTIME_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ - notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ - range, \ - constraint) \ - \ - lp64_product(bool, UseCompressedOops, false, \ +#ifdef _LP64 +#define LP64_RUNTIME_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ + \ + product(bool, UseCompressedOops, false, \ "Use 32-bit object references in 64-bit VM. " \ "lp64_product means flag is always constant in 32 bit VM") \ \ - lp64_product(bool, UseCompressedClassPointers, false, \ + product(bool, UseCompressedClassPointers, false, \ "Use 32-bit class pointers in 64-bit VM. " \ "lp64_product means flag is always constant in 32 bit VM") \ \ + product(intx, ObjectAlignmentInBytes, 8, \ + "Default object alignment in bytes, 8 is minimum") \ + range(8, 256) \ + constraint(ObjectAlignmentInBytesConstraintFunc, AtParse) + +#else +// !_LP64 + +#define LP64_RUNTIME_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) +const bool UseCompressedOops = false; +const bool UseCompressedClassPointers = false; +const intx ObjectAlignmentInBytes = 8; + +#endif // _LP64 + +#define RUNTIME_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + notproduct, \ + range, \ + constraint) \ + \ notproduct(bool, CheckCompressedOops, true, \ "Generate checks in encoding/decoding code in debug VM") \ \ @@ -143,24 +168,19 @@ const size_t minimumSymbolTableSize = 1024; "region.") \ range(1, max_uintx) \ \ - lp64_product(intx, ObjectAlignmentInBytes, 8, \ - "Default object alignment in bytes, 8 is minimum") \ - range(8, 256) \ - constraint(ObjectAlignmentInBytesConstraintFunc,AtParse) \ - \ develop(bool, CleanChunkPoolAsync, true, \ "Clean the chunk pool asynchronously") \ \ - diagnostic(uint, HandshakeTimeout, 0, \ + product(uint, HandshakeTimeout, 0, DIAGNOSTIC, \ "If nonzero set a timeout in milliseconds for handshakes") \ \ - experimental(bool, AlwaysSafeConstructors, false, \ + product(bool, AlwaysSafeConstructors, false, EXPERIMENTAL, \ "Force safe construction, as if all fields are final.") \ \ - diagnostic(bool, UnlockDiagnosticVMOptions, trueInDebug, \ + product(bool, UnlockDiagnosticVMOptions, trueInDebug, DIAGNOSTIC, \ "Enable normal processing of flags relating to field diagnostics")\ \ - experimental(bool, UnlockExperimentalVMOptions, false, \ + product(bool, UnlockExperimentalVMOptions, false, EXPERIMENTAL, \ "Enable normal processing of flags relating to experimental " \ "features") \ \ @@ -189,7 +209,7 @@ const size_t minimumSymbolTableSize = 1024; \ product(size_t, NUMAInterleaveGranularity, 2*M, \ "Granularity to use for NUMA interleaving on Windows OS") \ - range(os::vm_allocation_granularity(), NOT_LP64(2*G) LP64_ONLY(8192*G)) \ + constraint(NUMAInterleaveGranularityConstraintFunc, AtParse) \ \ product(uintx, NUMAChunkResizeWeight, 20, \ "Percentage (0-100) used to weight the current sample when " \ @@ -220,7 +240,7 @@ const size_t minimumSymbolTableSize = 1024; product(bool, UseSHA, false, \ "Control whether SHA instructions are used when available") \ \ - diagnostic(bool, UseGHASHIntrinsics, false, \ + product(bool, UseGHASHIntrinsics, false, DIAGNOSTIC, \ "Use intrinsics for GHASH versions of crypto") \ \ product(bool, UseBASE64Intrinsics, false, \ @@ -243,15 +263,12 @@ const size_t minimumSymbolTableSize = 1024; develop(bool, TraceRelocator, false, \ "Trace the bytecode relocator") \ \ - develop(bool, TraceLongCompiles, false, \ - "Print out every time compilation is longer than " \ - "a given threshold") \ \ - diagnostic(bool, SafepointALot, false, \ + product(bool, SafepointALot, false, DIAGNOSTIC, \ "Generate a lot of safepoints. This works with " \ "GuaranteedSafepointInterval") \ \ - diagnostic(bool, HandshakeALot, false, \ + product(bool, HandshakeALot, false, DIAGNOSTIC, \ "Generate a lot of handshakes. This works with " \ "GuaranteedSafepointInterval") \ \ @@ -265,7 +282,7 @@ const size_t minimumSymbolTableSize = 1024; develop(bool, VerifyStack, false, \ "Verify stack of each thread when it is entering a runtime call") \ \ - diagnostic(bool, ForceUnreachable, false, \ + product(bool, ForceUnreachable, false, DIAGNOSTIC, \ "Make all non code cache addresses to be unreachable by " \ "forcing use of 64bit literal fixups") \ \ @@ -285,27 +302,27 @@ const size_t minimumSymbolTableSize = 1024; product(bool, UseInlineCaches, true, \ "Use Inline Caches for virtual calls ") \ \ - diagnostic(bool, InlineArrayCopy, true, \ + product(bool, InlineArrayCopy, true, DIAGNOSTIC, \ "Inline arraycopy native that is known to be part of " \ "base library DLL") \ \ - diagnostic(bool, InlineObjectHash, true, \ + product(bool, InlineObjectHash, true, DIAGNOSTIC, \ "Inline Object::hashCode() native that is known to be part " \ "of base library DLL") \ \ - diagnostic(bool, InlineNatives, true, \ + product(bool, InlineNatives, true, DIAGNOSTIC, \ "Inline natives that are known to be part of base library DLL") \ \ - diagnostic(bool, InlineMathNatives, true, \ + product(bool, InlineMathNatives, true, DIAGNOSTIC, \ "Inline SinD, CosD, etc.") \ \ - diagnostic(bool, InlineClassNatives, true, \ + product(bool, InlineClassNatives, true, DIAGNOSTIC, \ "Inline Class.isInstance, etc") \ \ - diagnostic(bool, InlineThreadNatives, true, \ + product(bool, InlineThreadNatives, true, DIAGNOSTIC, \ "Inline Thread.currentThread, etc") \ \ - diagnostic(bool, InlineUnsafeOps, true, \ + product(bool, InlineUnsafeOps, true, DIAGNOSTIC, \ "Inline memory ops (native methods) from Unsafe") \ \ product(bool, CriticalJNINatives, true, \ @@ -314,49 +331,49 @@ const size_t minimumSymbolTableSize = 1024; notproduct(bool, StressCriticalJNINatives, false, \ "Exercise register saving code in critical natives") \ \ - diagnostic(bool, UseAESIntrinsics, false, \ + product(bool, UseAESIntrinsics, false, DIAGNOSTIC, \ "Use intrinsics for AES versions of crypto") \ \ - diagnostic(bool, UseAESCTRIntrinsics, false, \ + product(bool, UseAESCTRIntrinsics, false, DIAGNOSTIC, \ "Use intrinsics for the paralleled version of AES/CTR crypto") \ \ - diagnostic(bool, UseMD5Intrinsics, false, \ + product(bool, UseMD5Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for MD5 crypto hash function") \ \ - diagnostic(bool, UseSHA1Intrinsics, false, \ + product(bool, UseSHA1Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for SHA-1 crypto hash function. " \ "Requires that UseSHA is enabled.") \ \ - diagnostic(bool, UseSHA256Intrinsics, false, \ + product(bool, UseSHA256Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for SHA-224 and SHA-256 crypto hash functions. " \ "Requires that UseSHA is enabled.") \ \ - diagnostic(bool, UseSHA512Intrinsics, false, \ + product(bool, UseSHA512Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for SHA-384 and SHA-512 crypto hash functions. " \ "Requires that UseSHA is enabled.") \ \ - diagnostic(bool, UseCRC32Intrinsics, false, \ + product(bool, UseCRC32Intrinsics, false, DIAGNOSTIC, \ "use intrinsics for java.util.zip.CRC32") \ \ - diagnostic(bool, UseCRC32CIntrinsics, false, \ + product(bool, UseCRC32CIntrinsics, false, DIAGNOSTIC, \ "use intrinsics for java.util.zip.CRC32C") \ \ - diagnostic(bool, UseAdler32Intrinsics, false, \ + product(bool, UseAdler32Intrinsics, false, DIAGNOSTIC, \ "use intrinsics for java.util.zip.Adler32") \ \ - diagnostic(bool, UseVectorizedMismatchIntrinsic, false, \ + product(bool, UseVectorizedMismatchIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of ArraysSupport.vectorizedMismatch()") \ \ - diagnostic(bool, UseCopySignIntrinsic, false, \ + product(bool, UseCopySignIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of Math.copySign") \ \ - diagnostic(bool, UseSignumIntrinsic, false, \ + product(bool, UseSignumIntrinsic, false, DIAGNOSTIC, \ "Enables intrinsification of Math.signum") \ \ - diagnostic(ccstrlist, DisableIntrinsic, "", \ + product(ccstrlist, DisableIntrinsic, "", DIAGNOSTIC, \ "do not expand intrinsics whose (internal) names appear here") \ \ - diagnostic(ccstrlist, ControlIntrinsic, "", \ + product(ccstrlist, ControlIntrinsic, "", DIAGNOSTIC, \ "Control intrinsics using a list of +/- (internal) names, " \ "separated by commas") \ \ @@ -389,13 +406,13 @@ const size_t minimumSymbolTableSize = 1024; "Time out and warn or fail after SafepointTimeoutDelay " \ "milliseconds if failed to reach safepoint") \ \ - diagnostic(bool, AbortVMOnSafepointTimeout, false, \ + product(bool, AbortVMOnSafepointTimeout, false, DIAGNOSTIC, \ "Abort upon failure to reach safepoint (see SafepointTimeout)") \ \ - diagnostic(bool, AbortVMOnVMOperationTimeout, false, \ + product(bool, AbortVMOnVMOperationTimeout, false, DIAGNOSTIC, \ "Abort upon failure to complete VM operation promptly") \ \ - diagnostic(intx, AbortVMOnVMOperationTimeoutDelay, 1000, \ + product(intx, AbortVMOnVMOperationTimeoutDelay, 1000, DIAGNOSTIC, \ "Delay in milliseconds for option AbortVMOnVMOperationTimeout") \ range(0, max_intx) \ \ @@ -418,17 +435,17 @@ const size_t minimumSymbolTableSize = 1024; product(bool, MaxFDLimit, true, \ "Bump the number of file descriptors to maximum (Unix only)") \ \ - diagnostic(bool, LogEvents, true, \ + product(bool, LogEvents, true, DIAGNOSTIC, \ "Enable the various ring buffer event logs") \ \ - diagnostic(uintx, LogEventsBufferEntries, 20, \ + product(uintx, LogEventsBufferEntries, 20, DIAGNOSTIC, \ "Number of ring buffer event logs") \ range(1, NOT_LP64(1*K) LP64_ONLY(1*M)) \ \ - diagnostic(bool, BytecodeVerificationRemote, true, \ + product(bool, BytecodeVerificationRemote, true, DIAGNOSTIC, \ "Enable the Java bytecode verifier for remote classes") \ \ - diagnostic(bool, BytecodeVerificationLocal, false, \ + product(bool, BytecodeVerificationLocal, false, DIAGNOSTIC, \ "Enable the Java bytecode verifier for local classes") \ \ develop(bool, ForceFloatExceptions, trueInDebug, \ @@ -515,16 +532,16 @@ const size_t minimumSymbolTableSize = 1024; product(ccstrlist, OnOutOfMemoryError, "", \ "Run user-defined commands on first java.lang.OutOfMemoryError") \ \ - manageable(bool, HeapDumpBeforeFullGC, false, \ + product(bool, HeapDumpBeforeFullGC, false, MANAGEABLE, \ "Dump heap to file before any major stop-the-world GC") \ \ - manageable(bool, HeapDumpAfterFullGC, false, \ + product(bool, HeapDumpAfterFullGC, false, MANAGEABLE, \ "Dump heap to file after any major stop-the-world GC") \ \ - manageable(bool, HeapDumpOnOutOfMemoryError, false, \ + product(bool, HeapDumpOnOutOfMemoryError, false, MANAGEABLE, \ "Dump heap to file when java.lang.OutOfMemoryError is thrown") \ \ - manageable(ccstr, HeapDumpPath, NULL, \ + product(ccstr, HeapDumpPath, NULL, MANAGEABLE, \ "When HeapDumpOnOutOfMemoryError is on, the path (filename or " \ "directory) of the dump file (defaults to java_pid<pid>.hprof " \ "in the working directory)") \ @@ -535,23 +552,23 @@ const size_t minimumSymbolTableSize = 1024; product(ccstr, NativeMemoryTracking, "off", \ "Native memory tracking options") \ \ - diagnostic(bool, PrintNMTStatistics, false, \ + product(bool, PrintNMTStatistics, false, DIAGNOSTIC, \ "Print native memory tracking summary data if it is on") \ \ - diagnostic(bool, LogCompilation, false, \ + product(bool, LogCompilation, false, DIAGNOSTIC, \ "Log compilation activity in detail to LogFile") \ \ product(bool, PrintCompilation, false, \ "Print compilations") \ \ - diagnostic(intx, RepeatCompilation, 0, \ + product(intx, RepeatCompilation, 0, DIAGNOSTIC, \ "Repeat compilation without installing code (number of times)") \ - range(0, max_jint) \ + range(0, max_jint) \ \ product(bool, PrintExtendedThreadInfo, false, \ "Print more information in thread dump") \ \ - diagnostic(intx, ScavengeRootsInCode, 2, \ + product(intx, ScavengeRootsInCode, 2, DIAGNOSTIC, \ "0: do not allow scavengable oops in the code cache; " \ "1: allow scavenging from the code cache; " \ "2: emit as many constants as the compiler can see") \ @@ -560,31 +577,31 @@ const size_t minimumSymbolTableSize = 1024; product(bool, AlwaysRestoreFPU, false, \ "Restore the FPU control word after every JNI call (expensive)") \ \ - diagnostic(bool, PrintCompilation2, false, \ + product(bool, PrintCompilation2, false, DIAGNOSTIC, \ "Print additional statistics per compilation") \ \ - diagnostic(bool, PrintAdapterHandlers, false, \ + product(bool, PrintAdapterHandlers, false, DIAGNOSTIC, \ "Print code generated for i2c/c2i adapters") \ \ - diagnostic(bool, VerifyAdapterCalls, trueInDebug, \ + product(bool, VerifyAdapterCalls, trueInDebug, DIAGNOSTIC, \ "Verify that i2c/c2i adapters are called properly") \ \ develop(bool, VerifyAdapterSharing, false, \ "Verify that the code for shared adapters is the equivalent") \ \ - diagnostic(bool, PrintAssembly, false, \ + product(bool, PrintAssembly, false, DIAGNOSTIC, \ "Print assembly code (using external disassembler.so)") \ \ - diagnostic(ccstr, PrintAssemblyOptions, NULL, \ + product(ccstr, PrintAssemblyOptions, NULL, DIAGNOSTIC, \ "Print options string passed to disassembler.so") \ \ notproduct(bool, PrintNMethodStatistics, false, \ "Print a summary statistic for the generated nmethods") \ \ - diagnostic(bool, PrintNMethods, false, \ + product(bool, PrintNMethods, false, DIAGNOSTIC, \ "Print assembly code for nmethods when generated") \ \ - diagnostic(bool, PrintNativeNMethods, false, \ + product(bool, PrintNativeNMethods, false, DIAGNOSTIC, \ "Print assembly code for native nmethods when generated") \ \ develop(bool, PrintDebugInfo, false, \ @@ -616,10 +633,10 @@ const size_t minimumSymbolTableSize = 1024; "Print the code cache memory usage each time a method is " \ "compiled") \ \ - diagnostic(bool, PrintCodeHeapAnalytics, false, \ + product(bool, PrintCodeHeapAnalytics, false, DIAGNOSTIC, \ "Print code heap usage statistics on exit and on full condition") \ \ - diagnostic(bool, PrintStubCode, false, \ + product(bool, PrintStubCode, false, DIAGNOSTIC, \ "Print generated stub code") \ \ product(bool, StackTraceInThrowable, true, \ @@ -628,7 +645,7 @@ const size_t minimumSymbolTableSize = 1024; product(bool, OmitStackTraceInFastThrow, true, \ "Omit backtraces for some 'hot' exceptions in optimized code") \ \ - manageable(bool, ShowCodeDetailsInExceptionMessages, true, \ + product(bool, ShowCodeDetailsInExceptionMessages, true, MANAGEABLE, \ "Show exception messages from RuntimeExceptions that contain " \ "snippets of the failing code. Disable this to improve privacy.") \ \ @@ -675,7 +692,7 @@ const size_t minimumSymbolTableSize = 1024; notproduct(bool, PrintSystemDictionaryAtExit, false, \ "Print the system dictionary at exit") \ \ - diagnostic(bool, DynamicallyResizeSystemDictionaries, true, \ + product(bool, DynamicallyResizeSystemDictionaries, true, DIAGNOSTIC, \ "Dynamically resize system dictionaries as needed") \ \ product(bool, AlwaysLockClassLoader, false, \ @@ -690,24 +707,24 @@ const size_t minimumSymbolTableSize = 1024; product_pd(bool, DontYieldALot, \ "Throw away obvious excess yield calls") \ \ - experimental(bool, DisablePrimordialThreadGuardPages, false, \ + product(bool, DisablePrimordialThreadGuardPages, false, EXPERIMENTAL, \ "Disable the use of stack guard pages if the JVM is loaded " \ "on the primordial process thread") \ \ /* notice: the max range value here is max_jint, not max_intx */ \ /* because of overflow issue */ \ - diagnostic(intx, AsyncDeflationInterval, 250, \ + product(intx, AsyncDeflationInterval, 250, DIAGNOSTIC, \ "Async deflate idle monitors every so many milliseconds when " \ "MonitorUsedDeflationThreshold is exceeded (0 is off).") \ range(0, max_jint) \ \ - experimental(intx, MonitorUsedDeflationThreshold, 90, \ + product(intx, MonitorUsedDeflationThreshold, 90, EXPERIMENTAL, \ "Percentage of used monitors before triggering deflation (0 is " \ "off). The check is performed on GuaranteedSafepointInterval " \ "or AsyncDeflationInterval.") \ range(0, 100) \ \ - experimental(intx, hashCode, 5, \ + product(intx, hashCode, 5, EXPERIMENTAL, \ "(Unstable) select hashCode generation algorithm") \ \ product(bool, FilterSpuriousWakeups, true, \ @@ -792,7 +809,7 @@ const size_t minimumSymbolTableSize = 1024; range(0, (intx)(max_jint-(max_jint%PeriodicTask::interval_gran))) \ constraint(BiasedLockingStartupDelayFunc,AfterErgo) \ \ - diagnostic(bool, PrintBiasedLockingStatistics, false, \ + product(bool, PrintBiasedLockingStatistics, false, DIAGNOSTIC, \ "(Deprecated) Print statistics of biased locking in JVM") \ \ product(intx, BiasedLockingBulkRebiasThreshold, 20, \ @@ -814,7 +831,7 @@ const size_t minimumSymbolTableSize = 1024; range(500, max_intx) \ constraint(BiasedLockingDecayTimeFunc,AfterErgo) \ \ - diagnostic(intx, DiagnoseSyncOnPrimitiveWrappers, 0, \ + product(intx, DiagnoseSyncOnPrimitiveWrappers, 0, DIAGNOSTIC, \ "Detect and take action upon identifying synchronization on " \ "primitive wrappers. Modes: " \ "0: off; " \ @@ -918,20 +935,20 @@ const size_t minimumSymbolTableSize = 1024; product(bool, PrintHeapAtSIGBREAK, true, \ "Print heap layout in response to SIGBREAK") \ \ - manageable(bool, PrintClassHistogram, false, \ + product(bool, PrintClassHistogram, false, MANAGEABLE, \ "Print a histogram of class instances") \ \ - experimental(double, ObjectCountCutOffPercent, 0.5, \ + product(double, ObjectCountCutOffPercent, 0.5, EXPERIMENTAL, \ "The percentage of the used heap that the instances of a class " \ "must occupy for the class to generate a trace event") \ range(0.0, 100.0) \ \ /* JVMTI heap profiling */ \ \ - diagnostic(bool, TraceJVMTIObjectTagging, false, \ + product(bool, TraceJVMTIObjectTagging, false, DIAGNOSTIC, \ "Trace JVMTI object tagging calls") \ \ - diagnostic(bool, VerifyBeforeIteration, false, \ + product(bool, VerifyBeforeIteration, false, DIAGNOSTIC, \ "Verify memory system before JVMTI iteration") \ \ /* compiler interface */ \ @@ -939,7 +956,7 @@ const size_t minimumSymbolTableSize = 1024; develop(bool, CIPrintCompilerName, false, \ "when CIPrint is active, print the name of the active compiler") \ \ - diagnostic(bool, CIPrintCompileQueue, false, \ + product(bool, CIPrintCompileQueue, false, DIAGNOSTIC, \ "display the contents of the compile queue whenever a " \ "compilation is enqueued") \ \ @@ -989,11 +1006,11 @@ const size_t minimumSymbolTableSize = 1024; product(bool, UseDynamicNumberOfCompilerThreads, true, \ "Dynamically choose the number of parallel compiler threads") \ \ - diagnostic(bool, ReduceNumberOfCompilerThreads, true, \ + product(bool, ReduceNumberOfCompilerThreads, true, DIAGNOSTIC, \ "Reduce the number of parallel compiler threads when they " \ "are not used") \ \ - diagnostic(bool, TraceCompilerThreads, false, \ + product(bool, TraceCompilerThreads, false, DIAGNOSTIC, \ "Trace creation and removal of compiler threads") \ \ develop(bool, InjectCompilerCreationFailure, false, \ @@ -1012,7 +1029,7 @@ const size_t minimumSymbolTableSize = 1024; develop(bool, GenerateRangeChecks, true, \ "Generate range checks for array accesses") \ \ - diagnostic_pd(bool, ImplicitNullChecks, \ + product_pd(bool, ImplicitNullChecks, DIAGNOSTIC, \ "Generate code for implicit null checks") \ \ product_pd(bool, TrapBasedNullChecks, \ @@ -1021,10 +1038,10 @@ const size_t minimumSymbolTableSize = 1024; "null (+offset) will not raise a SIGSEGV, i.e.," \ "ImplicitNullChecks don't work (PPC64).") \ \ - diagnostic(bool, EnableThreadSMRExtraValidityChecks, true, \ + product(bool, EnableThreadSMRExtraValidityChecks, true, DIAGNOSTIC, \ "Enable Thread SMR extra validity checks") \ \ - diagnostic(bool, EnableThreadSMRStatistics, trueInDebug, \ + product(bool, EnableThreadSMRStatistics, trueInDebug, DIAGNOSTIC, \ "Enable Thread SMR Statistics") \ \ product(bool, UseNotificationThread, true, \ @@ -1042,7 +1059,7 @@ const size_t minimumSymbolTableSize = 1024; product(bool, UseTypeProfile, true, \ "Check interpreter profile for historically monomorphic calls") \ \ - diagnostic(bool, PrintInlining, false, \ + product(bool, PrintInlining, false, DIAGNOSTIC, \ "Print inlining optimizations") \ \ product(bool, UsePopCountInstruction, false, \ @@ -1051,10 +1068,10 @@ const size_t minimumSymbolTableSize = 1024; develop(bool, EagerInitialization, false, \ "Eagerly initialize classes if possible") \ \ - diagnostic(bool, LogTouchedMethods, false, \ + product(bool, LogTouchedMethods, false, DIAGNOSTIC, \ "Log methods which have been ever touched in runtime") \ \ - diagnostic(bool, PrintTouchedMethodsAtExit, false, \ + product(bool, PrintTouchedMethodsAtExit, false, DIAGNOSTIC, \ "Print all methods that have been ever touched in runtime") \ \ develop(bool, TraceMethodReplacement, false, \ @@ -1063,15 +1080,15 @@ const size_t minimumSymbolTableSize = 1024; develop(bool, PrintMethodFlushing, false, \ "Print the nmethods being flushed") \ \ - diagnostic(bool, PrintMethodFlushingStatistics, false, \ + product(bool, PrintMethodFlushingStatistics, false, DIAGNOSTIC, \ "print statistics about method flushing") \ \ - diagnostic(intx, HotMethodDetectionLimit, 100000, \ + product(intx, HotMethodDetectionLimit, 100000, DIAGNOSTIC, \ "Number of compiled code invocations after which " \ "the method is considered as hot by the flusher") \ range(1, max_jint) \ \ - diagnostic(intx, MinPassesBeforeFlush, 10, \ + product(intx, MinPassesBeforeFlush, 10, DIAGNOSTIC, \ "Minimum number of sweeper passes before an nmethod " \ "can be flushed") \ range(0, max_intx) \ @@ -1079,13 +1096,13 @@ const size_t minimumSymbolTableSize = 1024; product(bool, UseCodeAging, true, \ "Insert counter to detect warm methods") \ \ - diagnostic(bool, StressCodeAging, false, \ + product(bool, StressCodeAging, false, DIAGNOSTIC, \ "Start with counters compiled in") \ \ develop(bool, StressCodeBuffers, false, \ "Exercise code buffer expansion and other rare state changes") \ \ - diagnostic(bool, DebugNonSafepoints, trueInDebug, \ + product(bool, DebugNonSafepoints, trueInDebug, DIAGNOSTIC, \ "Generate extra debugging information for non-safepoints in " \ "nmethods") \ \ @@ -1111,16 +1128,16 @@ const size_t minimumSymbolTableSize = 1024; product(bool, PrintFlagsRanges, false, \ "Print VM flags and their ranges") \ \ - diagnostic(bool, SerializeVMOutput, true, \ + product(bool, SerializeVMOutput, true, DIAGNOSTIC, \ "Use a mutex to serialize output to tty and LogFile") \ \ - diagnostic(bool, DisplayVMOutput, true, \ + product(bool, DisplayVMOutput, true, DIAGNOSTIC, \ "Display all VM output on the tty, independently of LogVMOutput") \ \ - diagnostic(bool, LogVMOutput, false, \ + product(bool, LogVMOutput, false, DIAGNOSTIC, \ "Save VM output to LogFile") \ \ - diagnostic(ccstr, LogFile, NULL, \ + product(ccstr, LogFile, NULL, DIAGNOSTIC, \ "If LogVMOutput or LogCompilation is on, save VM output to " \ "this file [default: ./hotspot_pid%p.log] (%p replaced with pid)")\ \ @@ -1150,7 +1167,7 @@ const size_t minimumSymbolTableSize = 1024; product(bool, PrintStringTableStatistics, false, \ "print statistics about the StringTable and SymbolTable") \ \ - diagnostic(bool, VerifyStringTableAtExit, false, \ + product(bool, VerifyStringTableAtExit, false, DIAGNOSTIC, \ "verify StringTable contents at exit") \ \ notproduct(bool, PrintSymbolTableSizeHistogram, false, \ @@ -1160,11 +1177,11 @@ const size_t minimumSymbolTableSize = 1024; "standard exit from VM if bytecode verify error " \ "(only in debug mode)") \ \ - diagnostic(ccstr, AbortVMOnException, NULL, \ + product(ccstr, AbortVMOnException, NULL, DIAGNOSTIC, \ "Call fatal if this exception is thrown. Example: " \ "java -XX:AbortVMOnException=java.lang.NullPointerException Foo") \ \ - diagnostic(ccstr, AbortVMOnExceptionMessage, NULL, \ + product(ccstr, AbortVMOnExceptionMessage, NULL, DIAGNOSTIC, \ "Call fatal if the exception pointed by AbortVMOnException " \ "has this message") \ \ @@ -1248,7 +1265,7 @@ const size_t minimumSymbolTableSize = 1024; product_pd(bool, RewriteFrequentPairs, \ "Rewrite frequently used bytecode pairs into a single bytecode") \ \ - diagnostic(bool, PrintInterpreter, false, \ + product(bool, PrintInterpreter, false, DIAGNOSTIC, \ "Print the generated interpreter code") \ \ product(bool, UseInterpreter, true, \ @@ -1280,7 +1297,7 @@ const size_t minimumSymbolTableSize = 1024; develop(bool, PrintBytecodePairHistogram, false, \ "Print histogram of the executed bytecode pairs") \ \ - diagnostic(bool, PrintSignatureHandlers, false, \ + product(bool, PrintSignatureHandlers, false, DIAGNOSTIC, \ "Print code generated for native method signature handlers") \ \ develop(bool, VerifyOops, false, \ @@ -1328,7 +1345,7 @@ const size_t minimumSymbolTableSize = 1024; "CompileThreshold) before using the method's profile") \ range(0, 100) \ \ - diagnostic(bool, PrintMethodData, false, \ + product(bool, PrintMethodData, false, DIAGNOSTIC, \ "Print the results of +ProfileInterpreter at end of run") \ \ develop(bool, VerifyDataPointer, trueInDebug, \ @@ -1432,15 +1449,14 @@ const size_t minimumSymbolTableSize = 1024; \ /* notice: the max range value here is max_jint, not max_intx */ \ /* because of overflow issue */ \ - diagnostic(intx, GuaranteedSafepointInterval, 1000, \ + product(intx, GuaranteedSafepointInterval, 1000, DIAGNOSTIC, \ "Guarantee a safepoint (at least) every so many milliseconds " \ "(0 means none)") \ range(0, max_jint) \ \ product(intx, SafepointTimeoutDelay, 10000, \ "Delay in milliseconds for option SafepointTimeout") \ - LP64_ONLY(range(0, max_intx/MICROUNITS)) \ - NOT_LP64(range(0, max_intx)) \ + range(0, max_intx LP64_ONLY(/MICROUNITS)) \ \ product(intx, NmethodSweepActivity, 10, \ "Removes cold nmethods from code cache if > 0. Higher values " \ @@ -1493,7 +1509,7 @@ const size_t minimumSymbolTableSize = 1024; notproduct(intx, ZombieALotInterval, 5, \ "Number of exits until ZombieALot kicks in") \ \ - diagnostic(uintx, MallocMaxTestWords, 0, \ + product(uintx, MallocMaxTestWords, 0, DIAGNOSTIC, \ "If non-zero, maximum number of words that malloc/realloc can " \ "allocate (for testing only)") \ range(0, max_uintx) \ @@ -1517,7 +1533,7 @@ const size_t minimumSymbolTableSize = 1024; "Limit on traps (of one kind) in a method (includes inlines)") \ range(0, max_jint) \ \ - experimental(intx, PerMethodSpecTrapLimit, 5000, \ + product(intx, PerMethodSpecTrapLimit, 5000, EXPERIMENTAL, \ "Limit on speculative traps (of one kind) in a method " \ "(includes inlines)") \ range(0, max_jint) \ @@ -1526,14 +1542,14 @@ const size_t minimumSymbolTableSize = 1024; "Limit on traps (of one kind) at a particular BCI") \ range(0, max_jint) \ \ - experimental(intx, SpecTrapLimitExtraEntries, 3, \ + product(intx, SpecTrapLimitExtraEntries, 3, EXPERIMENTAL, \ "Extra method data trap entries for speculation") \ \ develop(intx, InlineFrequencyRatio, 20, \ "Ratio of call site execution to caller method invocation") \ range(0, max_jint) \ \ - diagnostic_pd(intx, InlineFrequencyCount, \ + product_pd(intx, InlineFrequencyCount, DIAGNOSTIC, \ "Count of call site execution necessary to trigger frequent " \ "inlining") \ range(0, max_jint) \ @@ -1564,14 +1580,14 @@ const size_t minimumSymbolTableSize = 1024; "class pointers are used") \ range(1*M, 3*G) \ \ - manageable(uintx, MinHeapFreeRatio, 40, \ + product(uintx, MinHeapFreeRatio, 40, MANAGEABLE, \ "The minimum percentage of heap free after GC to avoid expansion."\ " For most GCs this applies to the old generation. In G1 and" \ " ParallelGC it applies to the whole heap.") \ range(0, 100) \ constraint(MinHeapFreeRatioConstraintFunc,AfterErgo) \ \ - manageable(uintx, MaxHeapFreeRatio, 70, \ + product(uintx, MaxHeapFreeRatio, 70, MANAGEABLE, \ "The maximum percentage of heap free after GC to avoid shrinking."\ " For most GCs this applies to the old generation. In G1 and" \ " ParallelGC it applies to the whole heap.") \ @@ -1671,7 +1687,7 @@ const size_t minimumSymbolTableSize = 1024; \ product_pd(uintx, InitialCodeCacheSize, \ "Initial code cache size (in bytes)") \ - range(os::vm_page_size(), max_uintx) \ + constraint(VMPageSizeConstraintFunc, AtParse) \ \ develop_pd(uintx, CodeCacheMinimumUseSpace, \ "Minimum code cache size (in bytes) required to start VM.") \ @@ -1682,7 +1698,7 @@ const size_t minimumSymbolTableSize = 1024; \ product_pd(uintx, ReservedCodeCacheSize, \ "Reserved code cache size (in bytes) - maximum code cache size") \ - range(os::vm_page_size(), max_uintx) \ + constraint(VMPageSizeConstraintFunc, AtParse) \ \ product_pd(uintx, NonProfiledCodeHeapSize, \ "Size of code heap with non-profiled methods (in bytes)") \ @@ -1694,13 +1710,13 @@ const size_t minimumSymbolTableSize = 1024; \ product_pd(uintx, NonNMethodCodeHeapSize, \ "Size of code heap with non-nmethods (in bytes)") \ - range(os::vm_page_size(), max_uintx) \ + constraint(VMPageSizeConstraintFunc, AtParse) \ \ product_pd(uintx, CodeCacheExpansionSize, \ "Code cache expansion size (in bytes)") \ range(32*K, max_uintx) \ \ - diagnostic_pd(uintx, CodeCacheMinBlockLength, \ + product_pd(uintx, CodeCacheMinBlockLength, DIAGNOSTIC, \ "Minimum number of segments in a code cache block") \ range(1, 100) \ \ @@ -1722,19 +1738,19 @@ const size_t minimumSymbolTableSize = 1024; range(0, 100) \ \ /* AOT parameters */ \ - experimental(bool, UseAOT, false, \ + product(bool, UseAOT, false, EXPERIMENTAL, \ "Use AOT compiled files") \ \ - experimental(ccstrlist, AOTLibrary, NULL, \ + product(ccstrlist, AOTLibrary, NULL, EXPERIMENTAL, \ "AOT library") \ \ - experimental(bool, PrintAOT, false, \ + product(bool, PrintAOT, false, EXPERIMENTAL, \ "Print used AOT klasses and methods") \ \ notproduct(bool, PrintAOTStatistics, false, \ "Print AOT statistics") \ \ - diagnostic(bool, UseAOTStrictLoading, false, \ + product(bool, UseAOTStrictLoading, false, DIAGNOSTIC, \ "Exit the VM if any of the AOT libraries has invalid config") \ \ product(bool, CalculateClassFingerprint, false, \ @@ -1778,7 +1794,7 @@ const size_t minimumSymbolTableSize = 1024; product(ccstr, CompileCommandFile, NULL, \ "Read compiler commands from this file [.hotspot_compiler]") \ \ - diagnostic(ccstr, CompilerDirectivesFile, NULL, \ + product(ccstr, CompilerDirectivesFile, NULL, DIAGNOSTIC, \ "Read compiler directives from this file") \ \ product(ccstrlist, CompileCommand, "", \ @@ -1819,7 +1835,7 @@ const size_t minimumSymbolTableSize = 1024; notproduct(bool, CIObjectFactoryVerify, false, \ "enable potentially expensive verification in ciObjectFactory") \ \ - diagnostic(bool, AbortVMOnCompilationFailure, false, \ + product(bool, AbortVMOnCompilationFailure, false, DIAGNOSTIC, \ "Abort VM when method had failed to compile.") \ \ /* Priorities */ \ @@ -1900,10 +1916,10 @@ const size_t minimumSymbolTableSize = 1024; "Map Java priorities to OS priorities") \ range(-1, 127) \ \ - experimental(bool, UseCriticalJavaThreadPriority, false, \ + product(bool, UseCriticalJavaThreadPriority, false, EXPERIMENTAL, \ "Java thread priority 10 maps to critical scheduling priority") \ \ - experimental(bool, UseCriticalCompilerThreadPriority, false, \ + product(bool, UseCriticalCompilerThreadPriority, false, EXPERIMENTAL, \ "Compiler thread(s) run at critical scheduling priority") \ \ develop(intx, NewCodeParameter, 0, \ @@ -1914,10 +1930,6 @@ const size_t minimumSymbolTableSize = 1024; develop(intx, MinOopMapAllocation, 8, \ "Minimum number of OopMap entries in an OopMapSet") \ \ - /* Background Compilation */ \ - develop(intx, LongCompileThreshold, 50, \ - "Used with +TraceLongCompiles") \ - \ /* recompilation */ \ product_pd(intx, CompileThreshold, \ "number of interpreted method invocations before (re-)compiling") \ @@ -2012,21 +2024,21 @@ const size_t minimumSymbolTableSize = 1024; "if coming from AOT") \ range(0, max_jint) \ \ - diagnostic(intx, Tier0AOTInvocationThreshold, 200, \ + product(intx, Tier0AOTInvocationThreshold, 200, DIAGNOSTIC, \ "Switch to interpreter to profile if the number of method " \ "invocations crosses this threshold if coming from AOT " \ "(applicable only with " \ "CompilationMode=high-only|high-only-quick-internal)") \ range(0, max_jint) \ \ - diagnostic(intx, Tier0AOTMinInvocationThreshold, 100, \ + product(intx, Tier0AOTMinInvocationThreshold, 100, DIAGNOSTIC, \ "Minimum number of invocations to switch to interpreter " \ "to profile if coming from AOT " \ "(applicable only with " \ "CompilationMode=high-only|high-only-quick-internal)") \ range(0, max_jint) \ \ - diagnostic(intx, Tier0AOTCompileThreshold, 2000, \ + product(intx, Tier0AOTCompileThreshold, 2000, DIAGNOSTIC, \ "Threshold at which to switch to interpreter to profile " \ "if coming from AOT " \ "(invocation minimum must be satisfied, " \ @@ -2034,7 +2046,7 @@ const size_t minimumSymbolTableSize = 1024; "CompilationMode=high-only|high-only-quick-internal)") \ range(0, max_jint) \ \ - diagnostic(intx, Tier0AOTBackEdgeThreshold, 60000, \ + product(intx, Tier0AOTBackEdgeThreshold, 60000, DIAGNOSTIC, \ "Back edge threshold at which to switch to interpreter " \ "to profile if coming from AOT " \ "(applicable only with " \ @@ -2059,31 +2071,31 @@ const size_t minimumSymbolTableSize = 1024; "Back edge threshold at which tier 4 OSR compilation is invoked") \ range(0, max_jint) \ \ - diagnostic(intx, Tier40InvocationThreshold, 5000, \ + product(intx, Tier40InvocationThreshold, 5000, DIAGNOSTIC, \ "Compile if number of method invocations crosses this " \ "threshold (applicable only with " \ "CompilationMode=high-only|high-only-quick-internal)") \ range(0, max_jint) \ \ - diagnostic(intx, Tier40MinInvocationThreshold, 600, \ + product(intx, Tier40MinInvocationThreshold, 600, DIAGNOSTIC, \ "Minimum number of invocations to compile at tier 4 " \ "(applicable only with " \ "CompilationMode=high-only|high-only-quick-internal)") \ range(0, max_jint) \ \ - diagnostic(intx, Tier40CompileThreshold, 10000, \ + product(intx, Tier40CompileThreshold, 10000, DIAGNOSTIC, \ "Threshold at which tier 4 compilation is invoked (invocation " \ "minimum must be satisfied, applicable only with " \ "CompilationMode=high-only|high-only-quick-internal)") \ range(0, max_jint) \ \ - diagnostic(intx, Tier40BackEdgeThreshold, 15000, \ + product(intx, Tier40BackEdgeThreshold, 15000, DIAGNOSTIC, \ "Back edge threshold at which tier 4 OSR compilation is invoked " \ "(applicable only with " \ "CompilationMode=high-only|high-only-quick-internal)") \ range(0, max_jint) \ \ - diagnostic(intx, Tier0Delay, 5, \ + product(intx, Tier0Delay, 5, DIAGNOSTIC, \ "If C2 queue size grows over this amount per compiler thread " \ "do not start profiling in the interpreter " \ "(applicable only with " \ @@ -2178,13 +2190,13 @@ const size_t minimumSymbolTableSize = 1024; \ /* Flags used for temporary code during development */ \ \ - diagnostic(bool, UseNewCode, false, \ + product(bool, UseNewCode, false, DIAGNOSTIC, \ "Testing Only: Use the new version while testing") \ \ - diagnostic(bool, UseNewCode2, false, \ + product(bool, UseNewCode2, false, DIAGNOSTIC, \ "Testing Only: Use the new version while testing") \ \ - diagnostic(bool, UseNewCode3, false, \ + product(bool, UseNewCode3, false, DIAGNOSTIC, \ "Testing Only: Use the new version while testing") \ \ /* flags for performance data collection */ \ @@ -2243,7 +2255,7 @@ const size_t minimumSymbolTableSize = 1024; product(bool, EnableDynamicAgentLoading, true, \ "Allow tools to load agents with the attach mechanism") \ \ - manageable(bool, PrintConcurrentLocks, false, \ + product(bool, PrintConcurrentLocks, false, MANAGEABLE, \ "Print java.util.concurrent locks in thread dump") \ \ /* Shared spaces */ \ @@ -2284,25 +2296,25 @@ const size_t minimumSymbolTableSize = 1024; "Average number of symbols per bucket in shared table") \ range(2, 246) \ \ - diagnostic(bool, AllowArchivingWithJavaAgent, false, \ + product(bool, AllowArchivingWithJavaAgent, false, DIAGNOSTIC, \ "Allow Java agent to be run with CDS dumping") \ \ - diagnostic(bool, PrintMethodHandleStubs, false, \ + product(bool, PrintMethodHandleStubs, false, DIAGNOSTIC, \ "Print generated stub code for method handles") \ \ - diagnostic(bool, VerifyMethodHandles, trueInDebug, \ + product(bool, VerifyMethodHandles, trueInDebug, DIAGNOSTIC, \ "perform extra checks when constructing method handles") \ \ - diagnostic(bool, ShowHiddenFrames, false, \ + product(bool, ShowHiddenFrames, false, DIAGNOSTIC, \ "show method handle implementation frames (usually hidden)") \ \ - experimental(bool, TrustFinalNonStaticFields, false, \ + product(bool, TrustFinalNonStaticFields, false, EXPERIMENTAL, \ "trust final non-static declarations for constant folding") \ \ - diagnostic(bool, FoldStableValues, true, \ + product(bool, FoldStableValues, true, DIAGNOSTIC, \ "Optimize loads from stable fields (marked w/ @Stable)") \ \ - diagnostic(int, UseBootstrapCallInfo, 1, \ + product(int, UseBootstrapCallInfo, 1, DIAGNOSTIC, \ "0: when resolving InDy or ConDy, force all BSM arguments to be " \ "resolved before the bootstrap method is called; 1: when a BSM " \ "that may accept a BootstrapCallInfo is detected, use that API " \ @@ -2310,15 +2322,15 @@ const size_t minimumSymbolTableSize = 1024; "resolution; 2+: stress test the BCI API by calling more BSMs " \ "via that API, instead of with the eagerly-resolved array.") \ \ - diagnostic(bool, PauseAtStartup, false, \ + product(bool, PauseAtStartup, false, DIAGNOSTIC, \ "Causes the VM to pause at startup time and wait for the pause " \ "file to be removed (default: ./vm.paused.<pid>)") \ \ - diagnostic(ccstr, PauseAtStartupFile, NULL, \ + product(ccstr, PauseAtStartupFile, NULL, DIAGNOSTIC, \ "The file to create and for whose removal to await when pausing " \ "at startup. (default: ./vm.paused.<pid>)") \ \ - diagnostic(bool, PauseAtExit, false, \ + product(bool, PauseAtExit, false, DIAGNOSTIC, \ "Pause and wait for keypress on exit if a debugger is attached") \ \ product(bool, ExtendedDTraceProbes, false, \ @@ -2341,7 +2353,7 @@ const size_t minimumSymbolTableSize = 1024; "(will be rounded to nearest higher power of 2)") \ range(minimumStringTableSize, 16777216ul /* 2^24 */) \ \ - experimental(uintx, SymbolTableSize, defaultSymbolTableSize, \ + product(uintx, SymbolTableSize, defaultSymbolTableSize, EXPERIMENTAL, \ "Number of buckets in the JVM internal Symbol table") \ range(minimumSymbolTableSize, 16777216ul /* 2^24 */) \ \ @@ -2353,16 +2365,16 @@ const size_t minimumSymbolTableSize = 1024; "to be considered for deduplication") \ range(1, markWord::max_age) \ \ - diagnostic(bool, StringDeduplicationResizeALot, false, \ + product(bool, StringDeduplicationResizeALot, false, DIAGNOSTIC, \ "Force table resize every time the table is scanned") \ \ - diagnostic(bool, StringDeduplicationRehashALot, false, \ + product(bool, StringDeduplicationRehashALot, false, DIAGNOSTIC, \ "Force table rehash every time the table is scanned") \ \ - diagnostic(bool, WhiteBoxAPI, false, \ + product(bool, WhiteBoxAPI, false, DIAGNOSTIC, \ "Enable internal testing APIs") \ \ - experimental(intx, SurvivorAlignmentInBytes, 0, \ + product(intx, SurvivorAlignmentInBytes, 0, EXPERIMENTAL, \ "Default survivor space alignment in bytes") \ range(8, 256) \ constraint(SurvivorAlignmentInBytesConstraintFunc,AfterErgo) \ @@ -2383,7 +2395,7 @@ const size_t minimumSymbolTableSize = 1024; product(ccstr, ExtraSharedClassListFile, NULL, \ "Extra classlist for building the CDS archive file") \ \ - diagnostic(intx, ArchiveRelocationMode, 0, \ + product(intx, ArchiveRelocationMode, 0, DIAGNOSTIC, \ "(0) first map at preferred address, and if " \ "unsuccessful, map at alternative address (default); " \ "(1) always map at alternative address; " \ @@ -2391,21 +2403,21 @@ const size_t minimumSymbolTableSize = 1024; "do not map the archive") \ range(0, 2) \ \ - experimental(size_t, ArrayAllocatorMallocLimit, (size_t)-1, \ + product(size_t, ArrayAllocatorMallocLimit, (size_t)-1, EXPERIMENTAL, \ "Allocation less than this value will be allocated " \ "using malloc. Larger allocations will use mmap.") \ \ - experimental(bool, AlwaysAtomicAccesses, false, \ + product(bool, AlwaysAtomicAccesses, false, EXPERIMENTAL, \ "Accesses to all variables should always be atomic") \ \ - diagnostic(bool, UseUnalignedAccesses, false, \ + product(bool, UseUnalignedAccesses, false, DIAGNOSTIC, \ "Use unaligned memory accesses in Unsafe") \ \ product_pd(bool, PreserveFramePointer, \ "Use the FP register for holding the frame pointer " \ "and not as a general purpose register.") \ \ - diagnostic(bool, CheckIntrinsics, true, \ + product(bool, CheckIntrinsics, true, DIAGNOSTIC, \ "When a class C is loaded, check that " \ "(1) all intrinsics defined by the VM for class C are present "\ "in the loaded class file and are marked with the " \ @@ -2418,26 +2430,26 @@ const size_t minimumSymbolTableSize = 1024; "in the loaded class C. " \ "Check (3) is available only in debug builds.") \ \ - diagnostic_pd(intx, InitArrayShortSize, \ + product_pd(intx, InitArrayShortSize, DIAGNOSTIC, \ "Threshold small size (in bytes) for clearing arrays. " \ "Anything this size or smaller may get converted to discrete " \ "scalar stores.") \ range(0, max_intx) \ constraint(InitArrayShortSizeConstraintFunc, AfterErgo) \ \ - diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false, \ + product(bool, CompilerDirectivesIgnoreCompileCommands, false, DIAGNOSTIC, \ "Disable backwards compatibility for compile commands.") \ \ - diagnostic(bool, CompilerDirectivesPrint, false, \ + product(bool, CompilerDirectivesPrint, false, DIAGNOSTIC, \ "Print compiler directives on installation.") \ - diagnostic(int, CompilerDirectivesLimit, 50, \ + product(int, CompilerDirectivesLimit, 50, DIAGNOSTIC, \ "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.") \ \ - experimental(ccstr, AllocateOldGenAt, NULL, \ + product(ccstr, AllocateOldGenAt, NULL, EXPERIMENTAL, \ "Path to the directoy where a temporary file will be " \ "created to use as the backing store for old generation." \ "File of size Xmx is pre-allocated for performance reason, so" \ @@ -2447,10 +2459,10 @@ const size_t minimumSymbolTableSize = 1024; "Run periodic metaspace verifications (0 - none, " \ "1 - always, >1 every nth interval)") \ \ - diagnostic(bool, ShowRegistersOnAssert, true, \ + product(bool, ShowRegistersOnAssert, true, DIAGNOSTIC, \ "On internal errors, include registers in error report.") \ \ - diagnostic(bool, UseSwitchProfiling, true, \ + product(bool, UseSwitchProfiling, true, DIAGNOSTIC, \ "leverage profiling for table/lookup switch") \ \ develop(bool, TraceMemoryWriteback, false, \ @@ -2465,51 +2477,36 @@ const size_t minimumSymbolTableSize = 1024; JFR_ONLY(product(ccstr, StartFlightRecording, NULL, \ "Start flight recording with options")) \ \ - experimental(bool, UseFastUnorderedTimeStamps, false, \ + product(bool, UseFastUnorderedTimeStamps, false, EXPERIMENTAL, \ "Use platform unstable time where supported for timestamps only") \ \ product(bool, UseEmptySlotsInSupers, true, \ "Allow allocating fields in empty slots of super-classes") \ \ - diagnostic(bool, DeoptimizeNMethodBarriersALot, false, \ - "Make nmethod barriers deoptimise a lot.") \ + product(bool, DeoptimizeNMethodBarriersALot, false, DIAGNOSTIC, \ + "Make nmethod barriers deoptimise a lot.") + +// end of RUNTIME_FLAGS // Interface macros -#define DECLARE_PRODUCT_FLAG(type, name, value, doc) extern "C" type name; -#define DECLARE_PD_PRODUCT_FLAG(type, name, doc) extern "C" type name; -#define DECLARE_DIAGNOSTIC_FLAG(type, name, value, doc) extern "C" type name; -#define DECLARE_PD_DIAGNOSTIC_FLAG(type, name, doc) extern "C" type name; -#define DECLARE_EXPERIMENTAL_FLAG(type, name, value, doc) extern "C" type name; -#define DECLARE_MANAGEABLE_FLAG(type, name, value, doc) extern "C" type name; -#define DECLARE_PRODUCT_RW_FLAG(type, name, value, doc) extern "C" type name; +#define DECLARE_PRODUCT_FLAG(type, name, value, ...) extern "C" type name; +#define DECLARE_PD_PRODUCT_FLAG(type, name, ...) extern "C" type name; #ifdef PRODUCT -#define DECLARE_DEVELOPER_FLAG(type, name, value, doc) const type name = value; -#define DECLARE_PD_DEVELOPER_FLAG(type, name, doc) const type name = pd_##name; -#define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc) const type name = value; +#define DECLARE_DEVELOPER_FLAG(type, name, value, ...) const type name = value; +#define DECLARE_PD_DEVELOPER_FLAG(type, name, ...) const type name = pd_##name; +#define DECLARE_NOTPRODUCT_FLAG(type, name, value, ...) const type name = value; #else -#define DECLARE_DEVELOPER_FLAG(type, name, value, doc) extern "C" type name; -#define DECLARE_PD_DEVELOPER_FLAG(type, name, doc) extern "C" type name; -#define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc) extern "C" type name; +#define DECLARE_DEVELOPER_FLAG(type, name, value, ...) extern "C" type name; +#define DECLARE_PD_DEVELOPER_FLAG(type, name, ...) extern "C" type name; +#define DECLARE_NOTPRODUCT_FLAG(type, name, value, ...) extern "C" type name; #endif // PRODUCT -// Special LP64 flags, product only needed for now. -#ifdef _LP64 -#define DECLARE_LP64_PRODUCT_FLAG(type, name, value, doc) extern "C" type name; -#else -#define DECLARE_LP64_PRODUCT_FLAG(type, name, value, doc) const type name = value; -#endif // _LP64 -ALL_FLAGS(DECLARE_DEVELOPER_FLAG, \ - DECLARE_PD_DEVELOPER_FLAG, \ - DECLARE_PRODUCT_FLAG, \ - DECLARE_PD_PRODUCT_FLAG, \ - DECLARE_DIAGNOSTIC_FLAG, \ - DECLARE_PD_DIAGNOSTIC_FLAG, \ - DECLARE_EXPERIMENTAL_FLAG, \ - DECLARE_NOTPRODUCT_FLAG, \ - DECLARE_MANAGEABLE_FLAG, \ - DECLARE_PRODUCT_RW_FLAG, \ - DECLARE_LP64_PRODUCT_FLAG, \ - IGNORE_RANGE, \ +ALL_FLAGS(DECLARE_DEVELOPER_FLAG, + DECLARE_PD_DEVELOPER_FLAG, + DECLARE_PRODUCT_FLAG, + DECLARE_PD_PRODUCT_FLAG, + DECLARE_NOTPRODUCT_FLAG, + IGNORE_RANGE, IGNORE_CONSTRAINT) #endif // SHARE_RUNTIME_GLOBALS_HPP diff --git a/src/hotspot/share/runtime/globals_extension.hpp b/src/hotspot/share/runtime/globals_extension.hpp index 1116a6a023a..fd906760db9 100644 --- a/src/hotspot/share/runtime/globals_extension.hpp +++ b/src/hotspot/share/runtime/globals_extension.hpp @@ -34,34 +34,18 @@ #define FLAG_MEMBER_ENUM(name) Flag_##name##_enum #define FLAG_MEMBER_ENUM_(name) FLAG_MEMBER_ENUM(name), -#define FLAG_MEMBER_ENUM_PRODUCT(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_PD_PRODUCT(type, name, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_DIAGNOSTIC(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_PD_DIAGNOSTIC(type, name, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_EXPERIMENTAL(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_MANAGEABLE(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_PRODUCT_RW(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_DEVELOP(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_PD_DEVELOP(type, name, doc) FLAG_MEMBER_ENUM_(name) -#define FLAG_MEMBER_ENUM_NOTPRODUCT(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#ifdef _LP64 -#define FLAG_MEMBER_ENUM_LP64_PRODUCT(type, name, value, doc) FLAG_MEMBER_ENUM_(name) -#else -#define FLAG_MEMBER_ENUM_LP64_PRODUCT(type, name, value, doc) /* flag is constant */ -#endif // _LP64 - -typedef enum { +#define FLAG_MEMBER_ENUM_PRODUCT(type, name, value, ...) FLAG_MEMBER_ENUM_(name) +#define FLAG_MEMBER_ENUM_PD_PRODUCT(type, name, ...) FLAG_MEMBER_ENUM_(name) +#define FLAG_MEMBER_ENUM_DEVELOP(type, name, value, ...) FLAG_MEMBER_ENUM_(name) +#define FLAG_MEMBER_ENUM_PD_DEVELOP(type, name, ...) FLAG_MEMBER_ENUM_(name) +#define FLAG_MEMBER_ENUM_NOTPRODUCT(type, name, value, ...) FLAG_MEMBER_ENUM_(name) + +typedef enum : int { ALL_FLAGS(FLAG_MEMBER_ENUM_DEVELOP, FLAG_MEMBER_ENUM_PD_DEVELOP, FLAG_MEMBER_ENUM_PRODUCT, FLAG_MEMBER_ENUM_PD_PRODUCT, - FLAG_MEMBER_ENUM_DIAGNOSTIC, - FLAG_MEMBER_ENUM_PD_DIAGNOSTIC, - FLAG_MEMBER_ENUM_EXPERIMENTAL, FLAG_MEMBER_ENUM_NOTPRODUCT, - FLAG_MEMBER_ENUM_MANAGEABLE, - FLAG_MEMBER_ENUM_PRODUCT_RW, - FLAG_MEMBER_ENUM_LP64_PRODUCT, IGNORE_RANGE, IGNORE_CONSTRAINT) NUM_JVMFlagsEnum @@ -100,33 +84,17 @@ class JVMFlagEx : JVMFlag { #define FLAG_MEMBER_SET(name) Flag_##name##_set #define FLAG_MEMBER_SET_(type, name) inline JVMFlag::Error FLAG_MEMBER_SET(name)(type value, JVMFlag::Flags origin) { return JVMFlagEx::type##AtPut(FLAG_MEMBER_ENUM(name), value, origin); } -#define FLAG_MEMBER_SET_PRODUCT(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_PD_PRODUCT(type, name, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_DIAGNOSTIC(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_PD_DIAGNOSTIC(type, name, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_EXPERIMENTAL(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_MANAGEABLE(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_PRODUCT_RW(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_DEVELOP(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_PD_DEVELOP(type, name, doc) FLAG_MEMBER_SET_(type, name) -#define FLAG_MEMBER_SET_NOTPRODUCT(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#ifdef _LP64 -#define FLAG_MEMBER_SET_LP64_PRODUCT(type, name, value, doc) FLAG_MEMBER_SET_(type, name) -#else -#define FLAG_MEMBER_SET_LP64_PRODUCT(type, name, value, doc) /* flag is constant */ -#endif // _LP64 +#define FLAG_MEMBER_SET_PRODUCT(type, name, value, ...) FLAG_MEMBER_SET_(type, name) +#define FLAG_MEMBER_SET_PD_PRODUCT(type, name, ...) FLAG_MEMBER_SET_(type, name) +#define FLAG_MEMBER_SET_DEVELOP(type, name, value, ...) FLAG_MEMBER_SET_(type, name) +#define FLAG_MEMBER_SET_PD_DEVELOP(type, name, ...) FLAG_MEMBER_SET_(type, name) +#define FLAG_MEMBER_SET_NOTPRODUCT(type, name, value, ...) FLAG_MEMBER_SET_(type, name) ALL_FLAGS(FLAG_MEMBER_SET_DEVELOP, FLAG_MEMBER_SET_PD_DEVELOP, FLAG_MEMBER_SET_PRODUCT, FLAG_MEMBER_SET_PD_PRODUCT, - FLAG_MEMBER_SET_DIAGNOSTIC, - FLAG_MEMBER_SET_PD_DIAGNOSTIC, - FLAG_MEMBER_SET_EXPERIMENTAL, FLAG_MEMBER_SET_NOTPRODUCT, - FLAG_MEMBER_SET_MANAGEABLE, - FLAG_MEMBER_SET_PRODUCT_RW, - FLAG_MEMBER_SET_LP64_PRODUCT, IGNORE_RANGE, IGNORE_CONSTRAINT) diff --git a/src/hotspot/share/runtime/globals_shared.hpp b/src/hotspot/share/runtime/globals_shared.hpp index bca28da8dc8..36dc9409762 100644 --- a/src/hotspot/share/runtime/globals_shared.hpp +++ b/src/hotspot/share/runtime/globals_shared.hpp @@ -37,7 +37,7 @@ // parts of the memory system may require additional alignment // and are responsible for those alignments. #ifdef _LP64 -#define ScaleForWordSize(x) align_down_((x) * 13 / 10, HeapWordSize) +#define ScaleForWordSize(x) align_down((x) * 13 / 10, HeapWordSize) #else #define ScaleForWordSize(x) (x) #endif @@ -77,18 +77,14 @@ // Only materialize src code for contraint checking when required, ignore otherwise #define IGNORE_CONSTRAINT(func,type) +#define IGNORE_FLAG(...) + #define VM_FLAGS( \ develop, \ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ @@ -97,13 +93,7 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ @@ -112,100 +102,87 @@ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ +// Put the LP64/JVMCI/COMPILER1/COMPILER1/ARCH at +// the top, as they are processed by jvmFlags.cpp in that +// order. #define ALL_FLAGS( \ develop, \ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ - VM_FLAGS( \ + LP64_RUNTIME_FLAGS( \ develop, \ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ - manageable, \ - product_rw, \ - lp64_product, \ range, \ constraint) \ \ - RUNTIME_OS_FLAGS( \ + JVMCI_ONLY(JVMCI_FLAGS( \ develop, \ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ notproduct, \ range, \ - constraint) \ + constraint)) \ \ - JVMCI_ONLY(JVMCI_FLAGS( \ + COMPILER1_PRESENT(C1_FLAGS( \ develop, \ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ range, \ constraint)) \ \ - COMPILER1_PRESENT(C1_FLAGS( \ + COMPILER2_PRESENT(C2_FLAGS( \ develop, \ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ notproduct, \ range, \ constraint)) \ \ - COMPILER2_PRESENT(C2_FLAGS( \ + ARCH_FLAGS( \ + develop, \ + product, \ + notproduct, \ + range, \ + constraint) \ + \ + VM_FLAGS( \ develop, \ develop_pd, \ product, \ product_pd, \ - diagnostic, \ - diagnostic_pd, \ - experimental, \ notproduct, \ range, \ - constraint)) \ + constraint) \ \ - ARCH_FLAGS( \ + RUNTIME_OS_FLAGS( \ develop, \ + develop_pd, \ product, \ - diagnostic, \ - experimental, \ + product_pd, \ notproduct, \ range, \ constraint) +#define ALL_CONSTRAINTS(f) \ + COMPILER_CONSTRAINTS(f) \ + RUNTIME_CONSTRAINTS(f) \ + GC_CONSTRAINTS(f) + #endif // SHARE_RUNTIME_GLOBALS_SHARED_HPP diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp index e7875690ed1..89d27898186 100644 --- a/src/hotspot/share/runtime/handshake.cpp +++ b/src/hotspot/share/runtime/handshake.cpp @@ -141,7 +141,7 @@ class HandshakeSpinYield : public StackObj { // On UP this is always true. Thread* self = Thread::current(); if (self->is_Java_thread()) { - wait_blocked((JavaThread*)self, now); + wait_blocked(self->as_Java_thread(), now); } else { wait_raw(now); } @@ -393,7 +393,6 @@ void HandshakeState::set_operation(HandshakeOperation* op) { assert(Thread::current()->is_VM_thread(), "should be the VMThread"); _operation = op; } else { - assert(Thread::current()->is_Java_thread(), "should be a JavaThread"); // Serialize direct handshakes so that only one proceeds at a time for a given target _handshake_turn_sem.wait_with_safepoint_check(JavaThread::current()); _operation_direct = op; diff --git a/src/hotspot/share/runtime/interfaceSupport.cpp b/src/hotspot/share/runtime/interfaceSupport.cpp index 42d8d073872..98bbb5e8687 100644 --- a/src/hotspot/share/runtime/interfaceSupport.cpp +++ b/src/hotspot/share/runtime/interfaceSupport.cpp @@ -107,7 +107,7 @@ void InterfaceSupport::gc_alot() { Thread *thread = Thread::current(); if (!thread->is_Java_thread()) return; // Avoid concurrent calls // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC. - JavaThread *current_thread = (JavaThread *)thread; + JavaThread *current_thread = thread->as_Java_thread(); if (current_thread->active_handles() == NULL) return; // Short-circuit any possible re-entrant gc-a-lot attempt diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp index 45a931eef80..cb7154f7192 100644 --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp @@ -75,7 +75,7 @@ class ThreadStateTransition : public StackObj { public: ThreadStateTransition(JavaThread *thread) { _thread = thread; - assert(thread != NULL && thread->is_Java_thread(), "must be Java thread"); + assert(thread != NULL, "must be active Java thread"); } // Change threadstate in a manner, so safepoint can detect changes. @@ -186,7 +186,7 @@ class ThreadInVMfromUnknown { ThreadInVMfromUnknown() : _thread(NULL) { Thread* t = Thread::current(); if (t->is_Java_thread()) { - JavaThread* t2 = (JavaThread*) t; + JavaThread* t2 = t->as_Java_thread(); if (t2->thread_state() == _thread_in_native) { _thread = t2; ThreadStateTransition::transition_from_native(t2, _thread_in_vm); diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index dc1bc43a4ad..d40202beede 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -536,7 +536,7 @@ void vm_exit(int code) { // Historically there must have been some exit path for which // that was not the case and so we set it explicitly - even // though we no longer know what that path may be. - ((JavaThread*)thread)->set_thread_state(_thread_in_vm); + thread->as_Java_thread()->set_thread_state(_thread_in_vm); } // Fire off a VM_Exit operation to bring VM to a safepoint and exit @@ -577,7 +577,7 @@ void vm_perform_shutdown_actions() { if (thread != NULL && thread->is_Java_thread()) { // We are leaving the VM, set state to native (in case any OS exit // handlers call back to the VM) - JavaThread* jt = (JavaThread*)thread; + JavaThread* jt = thread->as_Java_thread(); // Must always be walkable or have no last_Java_frame when in // thread_in_native jt->frame_anchor()->make_walkable(jt); diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp index e08b1232777..72a87d6b9fc 100644 --- a/src/hotspot/share/runtime/javaCalls.cpp +++ b/src/hotspot/share/runtime/javaCalls.cpp @@ -52,7 +52,7 @@ // Implementation of JavaCallWrapper JavaCallWrapper::JavaCallWrapper(const methodHandle& callee_method, Handle receiver, JavaValue* result, TRAPS) { - JavaThread* thread = (JavaThread *)THREAD; + JavaThread* thread = THREAD->as_Java_thread(); bool clear_pending_exception = true; guarantee(thread->is_Java_thread(), "crucial check - the VM thread cannot and must not escape to Java code"); @@ -88,7 +88,7 @@ JavaCallWrapper::JavaCallWrapper(const methodHandle& callee_method, Handle recei THREAD->allow_unhandled_oop(&_receiver); #endif // CHECK_UNHANDLED_OOPS - _thread = (JavaThread *)thread; + _thread = thread; _handles = _thread->active_handles(); // save previous handle block & Java frame linkage // For the profiler, the last_Java_frame information in thread must always be in @@ -343,8 +343,7 @@ void JavaCalls::call(JavaValue* result, const methodHandle& method, JavaCallArgu void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) { - JavaThread* thread = (JavaThread*)THREAD; - assert(thread->is_Java_thread(), "must be called by a java thread"); + JavaThread* thread = THREAD->as_Java_thread(); assert(method.not_null(), "must have a method to call"); assert(!SafepointSynchronize::is_at_safepoint(), "call to Java code during VM operation"); assert(!thread->handle_area()->no_handle_mark_active(), "cannot call out to Java here"); diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp index 11c0bee4e89..a77d50500ae 100644 --- a/src/hotspot/share/runtime/jniHandles.cpp +++ b/src/hotspot/share/runtime/jniHandles.cpp @@ -206,7 +206,7 @@ jobjectRefType JNIHandles::handle_type(Thread* thread, jobject handle) { // Not in global storage. Might be a local handle. if (is_local_handle(thread, handle) || (thread->is_Java_thread() && - is_frame_handle((JavaThread*)thread, handle))) { + is_frame_handle(thread->as_Java_thread(), handle))) { result = JNILocalRefType; } break; @@ -301,7 +301,7 @@ void JNIHandles::verify() { bool JNIHandles::current_thread_in_native() { Thread* thread = Thread::current(); return (thread->is_Java_thread() && - JavaThread::current()->thread_state() == _thread_in_native); + thread->as_Java_thread()->thread_state() == _thread_in_native); } diff --git a/src/hotspot/share/runtime/mutex.cpp b/src/hotspot/share/runtime/mutex.cpp index 2211cd1221f..e8eb720e2a6 100644 --- a/src/hotspot/share/runtime/mutex.cpp +++ b/src/hotspot/share/runtime/mutex.cpp @@ -84,7 +84,7 @@ void Mutex::lock_contended(Thread* self) { // Is it a JavaThread participating in the safepoint protocol. if (is_active_Java_thread) { assert(rank() > Mutex::special, "Potential deadlock with special or lesser rank mutex"); - { ThreadBlockInVMWithDeadlockCheck tbivmdc((JavaThread *) self, &in_flight_mutex); + { ThreadBlockInVMWithDeadlockCheck tbivmdc(self->as_Java_thread(), &in_flight_mutex); in_flight_mutex = this; // save for ~ThreadBlockInVMWithDeadlockCheck _lock.lock(); } @@ -206,7 +206,7 @@ bool Monitor::wait_without_safepoint_check(int64_t timeout) { } bool Monitor::wait(int64_t timeout, bool as_suspend_equivalent) { - Thread* const self = Thread::current(); + JavaThread* const self = JavaThread::current(); // timeout is in milliseconds - with zero meaning never timeout assert(timeout >= 0, "negative timeout"); @@ -223,14 +223,14 @@ bool Monitor::wait(int64_t timeout, bool as_suspend_equivalent) { set_owner(NULL); // Check safepoint state after resetting owner and possible NSV. check_safepoint_state(self); - JavaThread *jt = (JavaThread *)self; + Mutex* in_flight_mutex = NULL; { - ThreadBlockInVMWithDeadlockCheck tbivmdc(jt, &in_flight_mutex); + ThreadBlockInVMWithDeadlockCheck tbivmdc(self, &in_flight_mutex); OSThreadWaitState osts(self->osthread(), false /* not Object.wait() */); if (as_suspend_equivalent) { - jt->set_suspend_equivalent(); + self->set_suspend_equivalent(); // cleared by handle_special_suspend_equivalent_condition() or // java_suspend_self() } @@ -239,13 +239,13 @@ bool Monitor::wait(int64_t timeout, bool as_suspend_equivalent) { in_flight_mutex = this; // save for ~ThreadBlockInVMWithDeadlockCheck // were we externally suspended while we were waiting? - if (as_suspend_equivalent && jt->handle_special_suspend_equivalent_condition()) { + if (as_suspend_equivalent && self->handle_special_suspend_equivalent_condition()) { // Our event wait has finished and we own the lock, but // while we were waiting another thread suspended us. We don't // want to hold the lock while suspended because that // would surprise the thread that suspended us. _lock.unlock(); - jt->java_suspend_self(); + self->java_suspend_self(); _lock.lock(); } } diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 90b1b2b9c28..5db41d59c0f 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -151,6 +151,7 @@ Mutex* CDSClassFileStream_lock = NULL; #endif Mutex* DumpTimeTable_lock = NULL; Mutex* CDSLambda_lock = NULL; +Mutex* DumpRegion_lock = NULL; #endif // INCLUDE_CDS #if INCLUDE_JVMCI @@ -346,6 +347,7 @@ void mutex_init() { #endif def(DumpTimeTable_lock , PaddedMutex , leaf - 1, true, _safepoint_check_never); def(CDSLambda_lock , PaddedMutex , leaf, true, _safepoint_check_never); + def(DumpRegion_lock , PaddedMutex , leaf, true, _safepoint_check_never); #endif // INCLUDE_CDS #if INCLUDE_JVMCI diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index fa82246169e..26103c85904 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -130,6 +130,7 @@ extern Mutex* CDSClassFileStream_lock; // FileMapInfo::open_stream_for #endif extern Mutex* DumpTimeTable_lock; // SystemDictionaryShared::find_or_allocate_info_for extern Mutex* CDSLambda_lock; // SystemDictionaryShared::get_shared_lambda_proxy_class +extern Mutex* DumpRegion_lock; // Symbol::operator new(size_t sz, int len) #endif // INCLUDE_CDS #if INCLUDE_JFR extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 226713c8363..b558e3f6252 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -276,9 +276,9 @@ bool ObjectMonitor::enter(TRAPS) { if (TrySpin(Self) > 0) { assert(_owner == Self, "must be Self: owner=" INTPTR_FORMAT, p2i(_owner)); assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions); - assert(((oop)object())->mark() == markWord::encode(this), + assert(object()->mark() == markWord::encode(this), "object mark must match encoded this: mark=" INTPTR_FORMAT - ", encoded this=" INTPTR_FORMAT, ((oop)object())->mark().value(), + ", encoded this=" INTPTR_FORMAT, object()->mark().value(), markWord::encode(this).value()); Self->_Stalled = 0; return true; @@ -286,8 +286,7 @@ bool ObjectMonitor::enter(TRAPS) { assert(_owner != Self, "invariant"); assert(_succ != Self, "invariant"); - assert(Self->is_Java_thread(), "invariant"); - JavaThread * jt = (JavaThread *) Self; + JavaThread * jt = Self->as_Java_thread(); assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); assert(jt->thread_state() != _thread_blocked, "invariant"); @@ -297,7 +296,7 @@ bool ObjectMonitor::enter(TRAPS) { // Async deflation is in progress and our contentions increment // above lost the race to async deflation. Undo the work and // force the caller to retry. - const oop l_object = (oop)object(); + const oop l_object = object(); if (l_object != NULL) { // Attempt to restore the header/dmw to the object's header so that // we only retry once if the deflater thread happens to be slow. @@ -311,8 +310,8 @@ bool ObjectMonitor::enter(TRAPS) { JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);) EventJavaMonitorEnter event; if (event.should_commit()) { - event.set_monitorClass(((oop)this->object())->klass()); - event.set_address((uintptr_t)(this->object_addr())); + event.set_monitorClass(object()->klass()); + event.set_address((uintptr_t)object_addr()); } { // Change java thread status to indicate blocked on monitor enter. @@ -375,7 +374,7 @@ bool ObjectMonitor::enter(TRAPS) { assert(_recursions == 0, "invariant"); assert(_owner == Self, "invariant"); assert(_succ != Self, "invariant"); - assert(((oop)(object()))->mark() == markWord::encode(this), "invariant"); + assert(object()->mark() == markWord::encode(this), "invariant"); // The thread -- now the owner -- is back in vm mode. // Report the glorious news via TI,DTrace and jvmstat. @@ -447,7 +446,7 @@ void ObjectMonitor::install_displaced_markword_in_object(const oop obj) { OrderAccess::loadload(); } - const oop l_object = (oop)object(); + const oop l_object = object(); if (l_object == NULL) { // ObjectMonitor's object ref has already been cleared by async // deflation so we're done here. @@ -506,8 +505,7 @@ const char* ObjectMonitor::is_busy_to_string(stringStream* ss) { void ObjectMonitor::EnterI(TRAPS) { Thread * const Self = THREAD; - assert(Self->is_Java_thread(), "invariant"); - assert(((JavaThread *) Self)->thread_state() == _thread_blocked, "invariant"); + assert(Self->as_Java_thread()->thread_state() == _thread_blocked, "invariant"); // Try the lock - TATAS if (TryLock (Self) > 0) { @@ -772,9 +770,10 @@ void ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) { assert(SelfNode != NULL, "invariant"); assert(SelfNode->_thread == Self, "invariant"); assert(_waiters > 0, "invariant"); - assert(((oop)(object()))->mark() == markWord::encode(this), "invariant"); - assert(((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant"); - JavaThread * jt = (JavaThread *) Self; + assert(object()->mark() == markWord::encode(this), "invariant"); + + JavaThread * jt = Self->as_Java_thread(); + assert(jt->thread_state() != _thread_blocked, "invariant"); int nWakeups = 0; for (;;) { @@ -840,7 +839,7 @@ void ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) { // In addition, Self.TState is stable. assert(_owner == Self, "invariant"); - assert(((oop)(object()))->mark() == markWord::encode(this), "invariant"); + assert(object()->mark() == markWord::encode(this), "invariant"); UnlinkAfterAcquire(Self, SelfNode); if (_succ == Self) _succ = NULL; assert(_succ != Self, "invariant"); @@ -1227,8 +1226,7 @@ void ObjectMonitor::ExitEpilog(Thread * Self, ObjectWaiter * Wakee) { // thread due to contention. intx ObjectMonitor::complete_exit(TRAPS) { Thread * const Self = THREAD; - assert(Self->is_Java_thread(), "Must be Java thread!"); - JavaThread *jt = (JavaThread *)THREAD; + JavaThread * jt = Self->as_Java_thread(); assert(InitDone, "Unexpectedly not initialized"); @@ -1253,8 +1251,7 @@ intx ObjectMonitor::complete_exit(TRAPS) { // complete_exit/reenter operate as a wait without waiting bool ObjectMonitor::reenter(intx recursions, TRAPS) { Thread * const Self = THREAD; - assert(Self->is_Java_thread(), "Must be Java thread!"); - JavaThread *jt = (JavaThread *)THREAD; + JavaThread * jt = Self->as_Java_thread(); guarantee(_owner != Self, "reenter already owner"); if (!enter(THREAD)) { @@ -1304,7 +1301,7 @@ static void post_monitor_wait_event(EventJavaMonitorWait* event, bool timedout) { assert(event != NULL, "invariant"); assert(monitor != NULL, "invariant"); - event->set_monitorClass(((oop)monitor->object())->klass()); + event->set_monitorClass(monitor->object()->klass()); event->set_timeout(timeout); event->set_address((uintptr_t)monitor->object_addr()); event->set_notifier(notifier_tid); @@ -1319,8 +1316,7 @@ static void post_monitor_wait_event(EventJavaMonitorWait* event, // will need to be replicated in complete_exit void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { Thread * const Self = THREAD; - assert(Self->is_Java_thread(), "Must be Java thread!"); - JavaThread *jt = (JavaThread *)THREAD; + JavaThread * jt = Self->as_Java_thread(); assert(InitDone, "Unexpectedly not initialized"); @@ -1523,7 +1519,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // Verify a few postconditions assert(_owner == Self, "invariant"); assert(_succ != Self, "invariant"); - assert(((oop)(object()))->mark() == markWord::encode(this), "invariant"); + assert(object()->mark() == markWord::encode(this), "invariant"); // check if the notification happened if (!WasNotified) { @@ -1948,12 +1944,12 @@ ObjectWaiter::ObjectWaiter(Thread* thread) { } void ObjectWaiter::wait_reenter_begin(ObjectMonitor * const mon) { - JavaThread *jt = (JavaThread *)this->_thread; + JavaThread *jt = this->_thread->as_Java_thread(); _active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon); } void ObjectWaiter::wait_reenter_end(ObjectMonitor * const mon) { - JavaThread *jt = (JavaThread *)this->_thread; + JavaThread *jt = this->_thread->as_Java_thread(); JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active); } @@ -2107,7 +2103,7 @@ void ObjectMonitor::print() const { print_on(tty); } void ObjectMonitor::print_debug_style_on(outputStream* st) const { st->print_cr("(ObjectMonitor*) " INTPTR_FORMAT " = {", p2i(this)); st->print_cr(" _header = " INTPTR_FORMAT, header().value()); - st->print_cr(" _object = " INTPTR_FORMAT, p2i(_object)); + st->print_cr(" _object = " INTPTR_FORMAT, p2i(object())); st->print(" _allocation_state = "); if (is_free()) { st->print("Free"); diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index b56207e314c..8a4eaf5bb5c 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -328,9 +328,9 @@ class ObjectMonitor { public: - void* object() const; - void* object_addr(); - void set_object(void* obj); + oop object() const; + oop* object_addr(); + void set_object(oop obj); void release_set_allocation_state(AllocationState s); void set_allocation_state(AllocationState s); AllocationState allocation_state() const; diff --git a/src/hotspot/share/runtime/objectMonitor.inline.hpp b/src/hotspot/share/runtime/objectMonitor.inline.hpp index a88b5c4a3b3..a55eb5b7f87 100644 --- a/src/hotspot/share/runtime/objectMonitor.inline.hpp +++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp @@ -92,22 +92,22 @@ inline void ObjectMonitor::clear_common() { assert(contentions() <= 0, "must not be positive: contentions=%d", contentions()); assert(_waiters == 0, "must be 0: waiters=%d", _waiters); assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions); - assert(_object != NULL, "must be non-NULL"); + assert(object() != NULL, "must be non-NULL"); set_allocation_state(Free); - _object = NULL; + set_object(NULL); } -inline void* ObjectMonitor::object() const { - return _object; +inline oop ObjectMonitor::object() const { + return (oop)_object; } -inline void* ObjectMonitor::object_addr() { - return (void *)(&_object); +inline oop* ObjectMonitor::object_addr() { + return (oop*)&_object; } -inline void ObjectMonitor::set_object(void* obj) { - _object = obj; +inline void ObjectMonitor::set_object(oop obj) { + _object = (void*)obj; } // Return number of threads contending for this monitor. diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index a10c7ba2f55..2a3621f3712 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1375,7 +1375,7 @@ bool os::stack_shadow_pages_available(Thread *thread, const methodHandle& method const int framesize_in_bytes = Interpreter::size_top_interpreter_activation(method()) * wordSize; - address limit = ((JavaThread*)thread)->stack_end() + + address limit = thread->as_Java_thread()->stack_end() + (JavaThread::stack_guard_zone_size() + JavaThread::stack_shadow_zone_size()); return sp > (limit + framesize_in_bytes); diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp index d42d864c2d9..50bb12861fe 100644 --- a/src/hotspot/share/runtime/reflection.cpp +++ b/src/hotspot/share/runtime/reflection.cpp @@ -1033,7 +1033,7 @@ static oop invoke(InstanceKlass* klass, // JVMTI has already reported the pending exception // JVMTI internal flag reset is needed in order to report InvocationTargetException if (THREAD->is_Java_thread()) { - JvmtiExport::clear_detected_exception((JavaThread*)THREAD); + JvmtiExport::clear_detected_exception(THREAD->as_Java_thread()); } JavaCallArguments args(Handle(THREAD, resolution_exception)); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), @@ -1147,7 +1147,7 @@ static oop invoke(InstanceKlass* klass, // JVMTI has already reported the pending exception // JVMTI internal flag reset is needed in order to report InvocationTargetException if (THREAD->is_Java_thread()) { - JvmtiExport::clear_detected_exception((JavaThread*)THREAD); + JvmtiExport::clear_detected_exception(THREAD->as_Java_thread()); } JavaCallArguments args(Handle(THREAD, target_exception)); diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp index 9e167d53070..bc25b4032fb 100644 --- a/src/hotspot/share/runtime/safepoint.cpp +++ b/src/hotspot/share/runtime/safepoint.cpp @@ -693,7 +693,6 @@ static void check_for_lazy_critical_native(JavaThread *thread, JavaThreadState s void SafepointSynchronize::block(JavaThread *thread) { assert(thread != NULL, "thread must be set"); - assert(thread->is_Java_thread(), "not a Java thread"); // Threads shouldn't block if they are in the middle of printing, but... ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id()); @@ -783,7 +782,6 @@ void SafepointSynchronize::block(JavaThread *thread) { void SafepointSynchronize::handle_polling_page_exception(JavaThread *thread) { - assert(thread->is_Java_thread(), "polling reference encountered by VM thread"); assert(thread->thread_state() == _thread_in_Java, "should come from Java code"); if (log_is_enabled(Info, safepoint, stats)) { diff --git a/src/hotspot/share/runtime/safepointMechanism.inline.hpp b/src/hotspot/share/runtime/safepointMechanism.inline.hpp index cec1513cbd5..9410544c076 100644 --- a/src/hotspot/share/runtime/safepointMechanism.inline.hpp +++ b/src/hotspot/share/runtime/safepointMechanism.inline.hpp @@ -40,7 +40,7 @@ bool SafepointMechanism::global_poll() { bool SafepointMechanism::local_poll(Thread* thread) { if (thread->is_Java_thread()) { - return local_poll_armed((JavaThread*)thread); + return local_poll_armed(thread->as_Java_thread()); } else { // If the poll is on a non-java thread we can only check the global state. return global_poll(); diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 256f42b5485..63922c34c0f 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -950,7 +950,7 @@ JRT_END jlong SharedRuntime::get_java_tid(Thread* thread) { if (thread != NULL) { if (thread->is_Java_thread()) { - oop obj = ((JavaThread*)thread)->threadObj(); + oop obj = thread->as_Java_thread()->threadObj(); return (obj == NULL) ? 0 : java_lang_Thread::thread_id(obj); } } @@ -3147,9 +3147,8 @@ void AdapterHandlerLibrary::print_statistics() { #endif /* PRODUCT */ JRT_LEAF(void, SharedRuntime::enable_stack_reserved_zone(JavaThread* thread)) - assert(thread->is_Java_thread(), "Only Java threads have a stack reserved zone"); if (thread->stack_reserved_zone_disabled()) { - thread->enable_stack_reserved_zone(); + thread->enable_stack_reserved_zone(); } thread->set_reserved_stack_activation(thread->stack_base()); JRT_END diff --git a/src/hotspot/share/runtime/sweeper.cpp b/src/hotspot/share/runtime/sweeper.cpp index 04e3ec8e131..cffae92ccc2 100644 --- a/src/hotspot/share/runtime/sweeper.cpp +++ b/src/hotspot/share/runtime/sweeper.cpp @@ -158,8 +158,7 @@ class NMethodMarkingClosure : public HandshakeClosure { NMethodMarkingClosure(CodeBlobClosure* cl) : HandshakeClosure("NMethodMarking"), _cl(cl) {} void do_thread(Thread* thread) { if (thread->is_Java_thread() && ! thread->is_Code_cache_sweeper_thread()) { - JavaThread* jt = (JavaThread*) thread; - jt->nmethods_do(_cl); + thread->as_Java_thread()->nmethods_do(_cl); } } }; diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 2585f4b3e9e..8b47d243ee1 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -449,8 +449,7 @@ static ObjectMonitor* take_from_start_of_om_free_list(Thread* self) { bool ObjectSynchronizer::quick_notify(oopDesc* obj, Thread* self, bool all) { assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); - assert(self->is_Java_thread(), "invariant"); - assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant"); + assert(self->as_Java_thread()->thread_state() == _thread_in_Java, "invariant"); NoSafepointVerifier nsv; if (obj == NULL) return false; // slow-path for invalid obj const markWord mark = obj->mark(); @@ -463,7 +462,7 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, Thread* self, bool all) { if (mark.has_monitor()) { ObjectMonitor* const mon = mark.monitor(); - assert(mon->object() == obj, "invariant"); + assert(mon->object() == oop(obj), "invariant"); if (mon->owner() != self) return false; // slow-path for IMS exception if (mon->first_waiter() != NULL) { @@ -499,8 +498,7 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, Thread* self, bool all) { bool ObjectSynchronizer::quick_enter(oop obj, Thread* self, BasicLock * lock) { assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); - assert(self->is_Java_thread(), "invariant"); - assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant"); + assert(self->as_Java_thread()->thread_state() == _thread_in_Java, "invariant"); NoSafepointVerifier nsv; if (obj == NULL) return false; // Need to throw NPE @@ -560,8 +558,7 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self, // Handle notifications when synchronizing on primitive wrappers void ObjectSynchronizer::handle_sync_on_primitive_wrapper(Handle obj, Thread* current) { - assert(current->is_Java_thread(), "must be for java object synchronization"); - JavaThread* self = (JavaThread*) current; + JavaThread* self = current->as_Java_thread(); frame last_frame = self->last_frame(); if (last_frame.is_interpreted_frame()) { @@ -686,7 +683,7 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) { // Java Monitor can be asynchronously inflated by a thread that // does not own the Java Monitor. ObjectMonitor* m = mark.monitor(); - assert(((oop)(m->object()))->mark() == mark, "invariant"); + assert(m->object()->mark() == mark, "invariant"); assert(m->is_entered(THREAD), "invariant"); } } @@ -1428,7 +1425,7 @@ void ObjectSynchronizer::list_oops_do(ObjectMonitor* list, OopClosure* f) { // so no need to lock ObjectMonitors for the list traversal. for (ObjectMonitor* mid = list; mid != NULL; mid = unmarked_next(mid)) { if (mid->object() != NULL) { - f->do_oop((oop*)mid->object_addr()); + f->do_oop(mid->object_addr()); } } } @@ -2149,7 +2146,7 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid, "must be no entering threads: EntryList=" INTPTR_FORMAT, p2i(mid->_EntryList)); - const oop obj = (oop) mid->object(); + const oop obj = mid->object(); if (log_is_enabled(Trace, monitorinflation)) { ResourceMark rm; log_trace(monitorinflation)("deflate_monitor_using_JT: " @@ -2426,7 +2423,6 @@ void ObjectSynchronizer::deflate_idle_monitors_using_JT() { // Deflate global idle ObjectMonitors using a JavaThread. // void ObjectSynchronizer::deflate_global_idle_monitors_using_JT() { - assert(Thread::current()->is_Java_thread(), "precondition"); JavaThread* self = JavaThread::current(); deflate_common_idle_monitors_using_JT(true /* is_global */, self); @@ -2871,7 +2867,7 @@ void ObjectSynchronizer::chk_in_use_entry(JavaThread* jt, ObjectMonitor* n, } *error_cnt_p = *error_cnt_p + 1; } - const oop obj = (oop)n->object(); + const oop obj = n->object(); const markWord mark = obj->mark(); if (!mark.has_monitor()) { if (jt != NULL) { @@ -2981,7 +2977,7 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out) { if ((cur = get_list_head_locked(&om_list_globals._in_use_list)) != NULL) { // Marked the global in-use list head so process the list. while (true) { - const oop obj = (oop) cur->object(); + const oop obj = cur->object(); const markWord mark = cur->header(); ResourceMark rm; out->print(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(cur), @@ -3011,7 +3007,7 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out) { if ((cur = get_list_head_locked(&jt->om_in_use_list)) != NULL) { // Marked the global in-use list head so process the list. while (true) { - const oop obj = (oop) cur->object(); + const oop obj = cur->object(); const markWord mark = cur->header(); ResourceMark rm; out->print(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index de4ec7eae13..204cd033589 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -355,8 +355,8 @@ void Thread::record_stack_base_and_size() { // Set stack limits after thread is initialized. if (is_Java_thread()) { - ((JavaThread*) this)->set_stack_overflow_limit(); - ((JavaThread*) this)->set_reserved_stack_activation(stack_base()); + as_Java_thread()->set_stack_overflow_limit(); + as_Java_thread()->set_reserved_stack_activation(stack_base()); } } @@ -483,9 +483,9 @@ Thread::~Thread() { // void Thread::check_for_dangling_thread_pointer(Thread *thread) { assert(!thread->is_Java_thread() || Thread::current() == thread || - !((JavaThread *) thread)->on_thread_list() || + !thread->as_Java_thread()->on_thread_list() || SafepointSynchronize::is_at_safepoint() || - ThreadsSMRSupport::is_a_protected_JavaThread_with_lock((JavaThread *) thread), + ThreadsSMRSupport::is_a_protected_JavaThread_with_lock(thread->as_Java_thread()), "possibility of dangling Thread pointer"); } #endif @@ -514,7 +514,7 @@ void Thread::start(Thread* thread) { // Can not set it after the thread started because we do not know the // exact thread state at that time. It could be in MONITOR_WAIT or // in SLEEPING or some other state. - java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(), + java_lang_Thread::set_thread_status(thread->as_Java_thread()->threadObj(), java_lang_Thread::RUNNABLE); } os::start_thread(thread); @@ -527,7 +527,7 @@ class InstallAsyncExceptionClosure : public HandshakeClosure { InstallAsyncExceptionClosure(Handle throwable) : HandshakeClosure("InstallAsyncException"), _throwable(throwable) {} void do_thread(Thread* thr) { - JavaThread* target = (JavaThread*)thr; + JavaThread* target = thr->as_Java_thread(); // Note that this now allows multiple ThreadDeath exceptions to be // thrown at a thread. // The target thread has run and has not exited yet. @@ -1005,7 +1005,7 @@ void Thread::check_for_valid_safepoint_state() { // are held. check_possible_safepoint(); - if (((JavaThread*)this)->thread_state() != _thread_in_vm) { + if (this->as_Java_thread()->thread_state() != _thread_in_vm) { fatal("LEAF method calling lock?"); } @@ -1030,7 +1030,7 @@ bool Thread::set_as_starting_thread() { "_starting_thread=" INTPTR_FORMAT, p2i(_starting_thread)); // NOTE: this must be called inside the main thread. DEBUG_ONLY(_starting_thread = this;) - return os::create_main_thread((JavaThread*)this); + return os::create_main_thread(this->as_Java_thread()); } static void initialize_class(Symbol* class_name, TRAPS) { @@ -2278,12 +2278,11 @@ void JavaThread::cleanup_failed_attach_current_thread(bool is_daemon) { JavaThread* JavaThread::active() { Thread* thread = Thread::current(); if (thread->is_Java_thread()) { - return (JavaThread*) thread; + return thread->as_Java_thread(); } else { assert(thread->is_VM_thread(), "this must be a vm thread"); VM_Operation* op = ((VMThread*) thread)->vm_operation(); - JavaThread *ret=op == NULL ? NULL : (JavaThread *)op->calling_thread(); - assert(ret->is_Java_thread(), "must be a Java thread"); + JavaThread *ret = op == NULL ? NULL : op->calling_thread()->as_Java_thread(); return ret; } } @@ -2554,8 +2553,7 @@ int JavaThread::java_suspend_self() { return ret; } - assert(_anchor.walkable() || - (is_Java_thread() && !((JavaThread*)this)->has_last_Java_frame()), + assert(_anchor.walkable() || !has_last_Java_frame(), "must have walkable stack"); MonitorLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag); @@ -3202,10 +3200,9 @@ const char* JavaThread::get_thread_name() const { #ifdef ASSERT // early safepoints can hit while current thread does not yet have TLS if (!SafepointSynchronize::is_at_safepoint()) { - Thread *cur = Thread::current(); - if (!(cur->is_Java_thread() && cur == this)) { - // Current JavaThreads are allowed to get their own name without - // the Threads_lock. + // Current JavaThreads are allowed to get their own name without + // the Threads_lock. + if (Thread::current() != this) { assert_locked_or_safepoint_or_handshake(Threads_lock, this); } } diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index c8bfc1b7824..0c4668ce9fc 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -98,6 +98,8 @@ DEBUG_ONLY(class ResourceMark;) class WorkerThread; +class JavaThread; + // Class hierarchy // - Thread // - JavaThread @@ -501,6 +503,8 @@ class Thread: public ThreadShadow { // Casts virtual WorkerThread* as_Worker_thread() const { return NULL; } + inline JavaThread* as_Java_thread(); + inline const JavaThread* as_Java_thread() const; virtual char* name() const { return (char*)"Unknown thread"; } @@ -2110,9 +2114,7 @@ class JavaThread: public Thread { // Inline implementation of JavaThread::current inline JavaThread* JavaThread::current() { - Thread* thread = Thread::current(); - assert(thread->is_Java_thread(), "just checking"); - return (JavaThread*)thread; + return Thread::current()->as_Java_thread(); } inline CompilerThread* JavaThread::as_CompilerThread() { @@ -2209,6 +2211,16 @@ class CompilerThread : public JavaThread { void set_task(CompileTask* task) { _task = task; } }; +inline JavaThread* Thread::as_Java_thread() { + assert(is_Java_thread(), "incorrect cast to JavaThread"); + return static_cast<JavaThread*>(this); +} + +inline const JavaThread* Thread::as_Java_thread() const { + assert(is_Java_thread(), "incorrect cast to const JavaThread"); + return static_cast<const JavaThread*>(this); +} + inline CompilerThread* CompilerThread::current() { return JavaThread::current()->as_CompilerThread(); } diff --git a/src/hotspot/share/runtime/timer.cpp b/src/hotspot/share/runtime/timer.cpp index aa64cc2bff8..d810f4524db 100644 --- a/src/hotspot/share/runtime/timer.cpp +++ b/src/hotspot/share/runtime/timer.cpp @@ -42,6 +42,11 @@ jlong TimeHelper::millis_to_counter(jlong millis) { return millis * freq; } +jlong TimeHelper::micros_to_counter(jlong micros) { + jlong freq = os::elapsed_frequency() / MICROUNITS; + return micros * freq; +} + elapsedTimer::elapsedTimer(jlong time, jlong timeUnitsPerSecond) { _active = false; jlong osTimeUnitsPerSecond = os::elapsed_frequency(); diff --git a/src/hotspot/share/runtime/timer.hpp b/src/hotspot/share/runtime/timer.hpp index 5f9cb17e6f2..9e29072a124 100644 --- a/src/hotspot/share/runtime/timer.hpp +++ b/src/hotspot/share/runtime/timer.hpp @@ -77,6 +77,7 @@ class TimeHelper { static double counter_to_seconds(jlong counter); static double counter_to_millis(jlong counter); static jlong millis_to_counter(jlong millis); + static jlong micros_to_counter(jlong micros); }; #endif // SHARE_RUNTIME_TIMER_HPP diff --git a/src/hotspot/share/runtime/vframeArray.cpp b/src/hotspot/share/runtime/vframeArray.cpp index 759bb82445e..4221425738f 100644 --- a/src/hotspot/share/runtime/vframeArray.cpp +++ b/src/hotspot/share/runtime/vframeArray.cpp @@ -176,7 +176,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, bool is_top_frame, bool is_bottom_frame, int exec_mode) { - JavaThread* thread = (JavaThread*) Thread::current(); + JavaThread* thread = JavaThread::current(); bool realloc_failure_exception = thread->frames_to_pop_failed_realloc() > 0; diff --git a/src/hotspot/share/runtime/vmOperations.cpp b/src/hotspot/share/runtime/vmOperations.cpp index c54548a6a52..3b50a480d1a 100644 --- a/src/hotspot/share/runtime/vmOperations.cpp +++ b/src/hotspot/share/runtime/vmOperations.cpp @@ -150,9 +150,7 @@ void VM_DeoptimizeAll::doit() { void VM_ZombieAll::doit() { - JavaThread *thread = (JavaThread *)calling_thread(); - assert(thread->is_Java_thread(), "must be a Java thread"); - thread->make_zombies(); + calling_thread()->as_Java_thread()->make_zombies(); } #endif // !PRODUCT diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 669aeff7f1c..d69954a44ce 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -338,9 +338,9 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry; volatile_nonstatic_field(ConstantPoolCacheEntry, _f2, intx) \ volatile_nonstatic_field(ConstantPoolCacheEntry, _flags, intx) \ \ - /********************************/ \ - /* MethodOop-related structures */ \ - /********************************/ \ + /*****************************/ \ + /* Method related structures */ \ + /*****************************/ \ \ nonstatic_field(CheckedExceptionElement, class_cp_index, u2) \ nonstatic_field(LocalVariableTableElement, start_bci, u2) \ @@ -1284,9 +1284,9 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry; \ declare_toplevel_type(OopHandle) \ \ - /*************************************/ \ - /* MethodOop-related data structures */ \ - /*************************************/ \ + /**********************************/ \ + /* Method related data structures */ \ + /**********************************/ \ \ declare_toplevel_type(CheckedExceptionElement) \ declare_toplevel_type(LocalVariableTableElement) \ diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index d208264f202..f9eae673b36 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -309,8 +309,7 @@ void VMThread::run() { // Notify the VMThread that the last non-daemon JavaThread has terminated, // and wait until operation is performed. void VMThread::wait_for_vm_thread_exit() { - assert(Thread::current()->is_Java_thread(), "Should be a JavaThread"); - assert(((JavaThread*)Thread::current())->is_terminated(), "Should be terminated"); + assert(JavaThread::current()->is_terminated(), "Should be terminated"); { MonitorLocker mu(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag); _should_terminate = true; mu.notify(); @@ -377,9 +376,7 @@ class HandshakeALotClosure : public HandshakeClosure { HandshakeALotClosure() : HandshakeClosure("HandshakeALot") {} void do_thread(Thread* thread) { #ifdef ASSERT - assert(thread->is_Java_thread(), "must be"); - JavaThread* jt = (JavaThread*)thread; - jt->verify_states_for_handshake(); + thread->as_Java_thread()->verify_states_for_handshake(); #endif } }; @@ -446,9 +443,6 @@ void VMThread::loop() { // something. This will run all the clean-up processing that needs // to be done at a safepoint. SafepointSynchronize::begin(); - #ifdef ASSERT - if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot(); - #endif SafepointSynchronize::end(); _cur_vm_operation = NULL; } @@ -490,22 +484,7 @@ void VMThread::loop() { } else { // not a safepoint operation log_debug(vmthread)("Evaluating non-safepoint VM operation: %s", _cur_vm_operation->name()); - if (TraceLongCompiles) { - elapsedTimer t; - t.start(); - evaluate_operation(_cur_vm_operation); - t.stop(); - double secs = t.seconds(); - if (secs * 1e3 > LongCompileThreshold) { - // XXX - _cur_vm_operation should not be accessed after - // the completed count has been incremented; the waiting - // thread may have already freed this memory. - tty->print_cr("vm %s: %3.7f secs]", _cur_vm_operation->name(), secs); - } - } else { - evaluate_operation(_cur_vm_operation); - } - + evaluate_operation(_cur_vm_operation); _cur_vm_operation = NULL; } } diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index c7be958fd1d..e884a3f3580 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -1073,7 +1073,7 @@ void DebugOnCmdStartDCmd::execute(DCmdSource source, TRAPS) { char const* transport = NULL; char const* addr = NULL; jboolean is_first_start = JNI_FALSE; - JavaThread* thread = (JavaThread*) THREAD; + JavaThread* thread = THREAD->as_Java_thread(); jthread jt = JNIHandles::make_local(thread->threadObj()); ThreadToNativeFromVM ttn(thread); const char *error = "Could not find jdwp agent."; diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index 12e6160f83a..fa18c3093c4 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -2071,12 +2071,8 @@ JVM_ENTRY(jlong, jmm_GetOneThreadAllocatedMemory(JNIEnv *env, jlong thread_id)) "Invalid thread ID", -1); } - if (thread_id == 0) { - // current thread - if (THREAD->is_Java_thread()) { - return ((JavaThread*)THREAD)->cooked_allocated_bytes(); - } - return -1; + if (thread_id == 0) { // current thread + return thread->cooked_allocated_bytes(); } ThreadsListHandle tlh; diff --git a/src/hotspot/share/services/memoryPool.cpp b/src/hotspot/share/services/memoryPool.cpp index a60dcf6492e..e2159a12583 100644 --- a/src/hotspot/share/services/memoryPool.cpp +++ b/src/hotspot/share/services/memoryPool.cpp @@ -29,6 +29,7 @@ #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "services/lowMemoryDetector.hpp" diff --git a/src/hotspot/share/services/nmtCommon.hpp b/src/hotspot/share/services/nmtCommon.hpp index 7fb7975567b..ea2f396fa8b 100644 --- a/src/hotspot/share/services/nmtCommon.hpp +++ b/src/hotspot/share/services/nmtCommon.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" -#define CALC_OBJ_SIZE_IN_TYPE(obj, type) (align_up_(sizeof(obj), sizeof(type))/sizeof(type)) +#define CALC_OBJ_SIZE_IN_TYPE(obj, type) (align_up(sizeof(obj), sizeof(type))/sizeof(type)) // Native memory tracking level enum NMT_TrackingLevel { diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp index 28e054c0fb5..e31e935ad84 100644 --- a/src/hotspot/share/services/threadService.cpp +++ b/src/hotspot/share/services/threadService.cpp @@ -229,12 +229,12 @@ Handle ThreadService::get_current_contended_monitor(JavaThread* thread) { oop obj = NULL; if (wait_obj != NULL) { // thread is doing an Object.wait() call - obj = (oop) wait_obj->object(); + obj = wait_obj->object(); } else { ObjectMonitor *enter_obj = thread->current_pending_monitor(); if (enter_obj != NULL) { // thread is trying to enter() an ObjectMonitor. - obj = (oop) enter_obj->object(); + obj = enter_obj->object(); } } @@ -422,8 +422,7 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list, Thread* owner = waitingToLockRawMonitor->owner(); if (owner != NULL && // the raw monitor could be released at any time owner->is_Java_thread()) { - // only JavaThreads can be reported here - currentThread = (JavaThread*) owner; + currentThread = owner->as_Java_thread(); } } else if (waitingToLockMonitor != NULL) { address currentOwner = (address)waitingToLockMonitor->owner(); @@ -626,7 +625,7 @@ class InflatedMonitorsClosure: public MonitorClosure { } void do_monitor(ObjectMonitor* mid) { if (mid->owner() == _thread) { - oop object = (oop) mid->object(); + oop object = mid->object(); if (!_stack_trace->is_owned_monitor_on_stack(object)) { _stack_trace->add_jni_locked_monitor(object); } @@ -878,6 +877,8 @@ void ThreadSnapshot::initialize(ThreadsList * t_list, JavaThread* thread) { _is_ext_suspended = thread->is_being_ext_suspended(); _is_in_native = (thread->thread_state() == _thread_in_native); + Handle obj = ThreadService::get_current_contended_monitor(thread); + oop blocker_object = NULL; oop blocker_object_owner = NULL; @@ -885,7 +886,6 @@ void ThreadSnapshot::initialize(ThreadsList * t_list, JavaThread* thread) { _thread_status == java_lang_Thread::IN_OBJECT_WAIT || _thread_status == java_lang_Thread::IN_OBJECT_WAIT_TIMED) { - Handle obj = ThreadService::get_current_contended_monitor(thread); if (obj() == NULL) { // monitor no longer exists; thread is not blocked _thread_status = java_lang_Thread::RUNNABLE; @@ -986,7 +986,7 @@ void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const // Could be NULL as the raw monitor could be released at any time if held by non-JavaThread if (owner != NULL) { if (owner->is_Java_thread()) { - currentThread = (JavaThread*) owner; + currentThread = owner->as_Java_thread(); st->print_cr("%s \"%s\"", owner_desc, currentThread->get_thread_name()); } else { st->print_cr(",\n which has now been released"); @@ -998,7 +998,7 @@ void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const if (waitingToLockMonitor != NULL) { st->print(" waiting to lock monitor " INTPTR_FORMAT, p2i(waitingToLockMonitor)); - oop obj = (oop)waitingToLockMonitor->object(); + oop obj = waitingToLockMonitor->object(); st->print(" (object " INTPTR_FORMAT ", a %s)", p2i(obj), obj->klass()->external_name()); diff --git a/src/hotspot/share/services/writeableFlags.cpp b/src/hotspot/share/services/writeableFlags.cpp index f5d5e321b43..84aa9edc578 100644 --- a/src/hotspot/share/services/writeableFlags.cpp +++ b/src/hotspot/share/services/writeableFlags.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,12 +39,12 @@ static void buffer_concat(char* buffer, const char* src) { } static void print_flag_error_message_bounds(const JVMFlag* flag, char* buffer) { - JVMFlagRange* range = JVMFlagRangeList::find(flag); - if (range != NULL) { + JVMFlagRangeChecker range = JVMFlagRangeList::find(flag); + if (range.exists()) { buffer_concat(buffer, "must have value in range "); stringStream stream; - range->print(&stream); + range.print(&stream); const char* range_string = stream.as_string(); size_t j = strlen(buffer); for (size_t i=0; j<TEMP_BUF_SIZE-1; i++) { diff --git a/src/hotspot/share/utilities/align.hpp b/src/hotspot/share/utilities/align.hpp index 50c9808c7fa..7c7a4f67bc5 100644 --- a/src/hotspot/share/utilities/align.hpp +++ b/src/hotspot/share/utilities/align.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * 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,65 +25,64 @@ #ifndef SHARE_UTILITIES_ALIGN_HPP #define SHARE_UTILITIES_ALIGN_HPP +#include "metaprogramming/enableIf.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/powerOfTwo.hpp" - -// Signed variants of alignment helpers. There are two versions of each, a macro -// for use in places like enum definitions that require compile-time constant -// expressions and a function for all other places so as to get type checking. - -// Using '(what) & ~align_mask(alignment)' to align 'what' down is broken when -// 'alignment' is an unsigned int and 'what' is a wider type. The & operation -// will widen the inverted mask, and not sign extend it, leading to a mask with -// zeros in the most significant bits. The use of align_mask_widened() solves -// this problem. -#define align_mask(alignment) ((alignment) - 1) -#define widen_to_type_of(what, type_carrier) (true ? (what) : (type_carrier)) -#define align_mask_widened(alignment, type_carrier) widen_to_type_of(align_mask(alignment), (type_carrier)) - -#define align_down_(size, alignment) ((size) & ~align_mask_widened((alignment), (size))) - -#define align_up_(size, alignment) (align_down_((size) + align_mask(alignment), (alignment))) - -#define is_aligned_(size, alignment) (((size) & align_mask(alignment)) == 0) - -// Helpers to align sizes and check for alignment - -template <typename T, typename A> -inline T align_up(T size, A alignment) { - assert(is_power_of_2(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); - - T ret = align_up_(size, alignment); - assert(is_aligned_(ret, alignment), "must be aligned: " UINT64_FORMAT, (uint64_t)ret); - - return ret; +#include <type_traits> + +// Compute mask to use for aligning to or testing alignment. +// The alignment must be a power of 2. Returns alignment - 1, which is +// a mask with all bits set below alignment's single bit. +template<typename T, ENABLE_IF(std::is_integral<T>::value)> +static constexpr T alignment_mask(T alignment) { + assert(is_power_of_2(alignment), + "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); + return alignment - 1; } -template <typename T, typename A> -inline T align_down(T size, A alignment) { - assert(is_power_of_2(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); +// Some "integral" constant alignments are defined via enum. +template<typename T, ENABLE_IF(std::is_enum<T>::value)> +static constexpr auto alignment_mask(T alignment) { + return alignment_mask(static_cast<std::underlying_type_t<T>>(alignment)); +} - T ret = align_down_(size, alignment); - assert(is_aligned_(ret, alignment), "must be aligned: " UINT64_FORMAT, (uint64_t)ret); +// Align integers and check for alignment. +// The is_integral filtering here is not for disambiguation with the T* +// overloads; if those match then they are a better match. Rather, the +// is_integral filtering is to prevent back-sliding on the use of enums +// as "integral" constants that need aligning. - return ret; +template<typename T, typename A, ENABLE_IF(std::is_integral<T>::value)> +constexpr bool is_aligned(T size, A alignment) { + return (size & alignment_mask(alignment)) == 0; } -template <typename T, typename A> -inline bool is_aligned(T size, A alignment) { - assert(is_power_of_2(alignment), "must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment); +template<typename T, typename A, ENABLE_IF(std::is_integral<T>::value)> +constexpr T align_down(T size, A alignment) { + // Convert mask to T before logical_not. Otherwise, if alignment is unsigned + // and smaller than T, the result of the logical_not will be zero-extended + // by integral promotion, and upper bits of size will be discarded. + T result = size & ~T(alignment_mask(alignment)); + assert(is_aligned(result, alignment), + "must be aligned: " UINT64_FORMAT, (uint64_t)result); + return result; +} - return is_aligned_(size, alignment); +template<typename T, typename A, ENABLE_IF(std::is_integral<T>::value)> +constexpr T align_up(T size, A alignment) { + T adjusted = size + alignment_mask(alignment); + return align_down(adjusted, alignment); } // Align down with a lower bound. If the aligning results in 0, return 'alignment'. template <typename T, typename A> -inline T align_down_bounded(T size, A alignment) { - A aligned_size = align_down(size, alignment); - return aligned_size > 0 ? aligned_size : alignment; +constexpr T align_down_bounded(T size, A alignment) { + T aligned_size = align_down(size, alignment); + return (aligned_size > 0) ? aligned_size : T(alignment); } -// Helpers to align pointers and check for alignment. +// Align pointers and check for alignment. template <typename T, typename A> inline T* align_up(T* ptr, A alignment) { @@ -122,7 +121,7 @@ inline bool is_object_aligned(const void* addr) { // Pad out certain offsets to jlong alignment, in HeapWord units. template <typename T> -inline T align_object_offset(T offset) { +constexpr T align_object_offset(T offset) { return align_up(offset, HeapWordsPerLong); } diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 62d9a3ec14d..ebd2ffc2266 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -972,12 +972,12 @@ inline intptr_t bitfield(intptr_t x, int start_bit_no, int field_length) { // and 64-bit overloaded functions, which does not work, and having // explicitly-typed versions of these routines (i.e., MAX2I, MAX2L) // will be even more error-prone than macros. -template<class T> inline T MAX2(T a, T b) { return (a > b) ? a : b; } -template<class T> inline T MIN2(T a, T b) { return (a < b) ? a : b; } -template<class T> inline T MAX3(T a, T b, T c) { return MAX2(MAX2(a, b), c); } -template<class T> inline T MIN3(T a, T b, T c) { return MIN2(MIN2(a, b), c); } -template<class T> inline T MAX4(T a, T b, T c, T d) { return MAX2(MAX3(a, b, c), d); } -template<class T> inline T MIN4(T a, T b, T c, T d) { return MIN2(MIN3(a, b, c), d); } +template<class T> constexpr T MAX2(T a, T b) { return (a > b) ? a : b; } +template<class T> constexpr T MIN2(T a, T b) { return (a < b) ? a : b; } +template<class T> constexpr T MAX3(T a, T b, T c) { return MAX2(MAX2(a, b), c); } +template<class T> constexpr T MIN3(T a, T b, T c) { return MIN2(MIN2(a, b), c); } +template<class T> constexpr T MAX4(T a, T b, T c, T d) { return MAX2(MAX3(a, b, c), d); } +template<class T> constexpr T MIN4(T a, T b, T c, T d) { return MIN2(MIN3(a, b, c), d); } template<class T> inline T ABS(T x) { return (x > 0) ? x : -x; } diff --git a/src/hotspot/share/utilities/powerOfTwo.hpp b/src/hotspot/share/utilities/powerOfTwo.hpp index a8cc68fe506..fb96b1242f9 100644 --- a/src/hotspot/share/utilities/powerOfTwo.hpp +++ b/src/hotspot/share/utilities/powerOfTwo.hpp @@ -26,16 +26,17 @@ #define SHARE_UTILITIES_POWEROFTWO_HPP #include "metaprogramming/enableIf.hpp" -#include "metaprogramming/isIntegral.hpp" -#include "metaprogramming/isSigned.hpp" #include "utilities/count_leading_zeros.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include <limits> +#include <type_traits> // Power of two convenience library. -template <typename T> -bool is_power_of_2(T x) { +// Returns true iff there exists integer i such that (T(1) << i) == x. +template <typename T, ENABLE_IF(std::is_integral<T>::value)> +constexpr bool is_power_of_2(T x) { return (x > T(0)) && ((x & (x - 1)) == T(0)); } @@ -55,94 +56,36 @@ inline int exact_log2_long(jlong x) { return bits - count_leading_zeros(x) - 1; } -// Round down to the closest power of two greater to or equal to the given -// value. - -// Signed version: 0 is an invalid input, negative values are invalid -template <typename T> -inline typename EnableIf<IsSigned<T>::value, T>::type round_down_power_of_2(T value) { - STATIC_ASSERT(IsIntegral<T>::value); +// Round down to the closest power of two less than or equal to the given value. +// precondition: value > 0. +template<typename T, ENABLE_IF(std::is_integral<T>::value)> +inline T round_down_power_of_2(T value) { assert(value > 0, "Invalid value"); uint32_t lz = count_leading_zeros(value); - assert(lz < sizeof(T) * BitsPerByte, "Sanity"); - return T(1) << (sizeof(T) * BitsPerByte - 1 - lz); -} - -// Unsigned version: 0 is an invalid input -template <typename T> -inline typename EnableIf<!IsSigned<T>::value, T>::type round_down_power_of_2(T value) { - STATIC_ASSERT(IsIntegral<T>::value); - assert(value != 0, "Invalid value"); - uint32_t lz = count_leading_zeros(value); - assert(lz < sizeof(T) * BitsPerByte, "Sanity"); return T(1) << (sizeof(T) * BitsPerByte - 1 - lz); } -// Round up to the closest power of two greater to or equal to -// the given value. - -// Signed version: 0 is an invalid input, negative values are invalid, -// overflows with assert if value is larger than 2^30 or 2^62 for 32- and -// 64-bit integers, respectively -template <typename T> -inline typename EnableIf<IsSigned<T>::value, T>::type round_up_power_of_2(T value) { - STATIC_ASSERT(IsIntegral<T>::value); - STATIC_ASSERT(IsSigned<T>::value); +// Round up to the closest power of two greater to or equal to the given value. +// precondition: value > 0. +// precondition: value <= maximum power of two representable by T. +template<typename T, ENABLE_IF(std::is_integral<T>::value)> +inline T round_up_power_of_2(T value) { assert(value > 0, "Invalid value"); + const T max_value = std::numeric_limits<T>::max(); + assert(value <= (max_value - (max_value >> 1)), "Overflow"); if (is_power_of_2(value)) { return value; } uint32_t lz = count_leading_zeros(value); - assert(lz < sizeof(T) * BitsPerByte, "Sanity"); - assert(lz > 1, "Will overflow"); - return T(1) << (sizeof(T) * BitsPerByte - lz); -} - -// Unsigned version: 0 is an invalid input, overflows with assert if value -// is larger than 2^31 or 2^63 for 32- and 64-bit integers, respectively -template <typename T> -inline typename EnableIf<!IsSigned<T>::value, T>::type round_up_power_of_2(T value) { - STATIC_ASSERT(IsIntegral<T>::value); - STATIC_ASSERT(!IsSigned<T>::value); - assert(value != 0, "Invalid value"); - if (is_power_of_2(value)) { - return value; - } - uint32_t lz = count_leading_zeros(value); - assert(lz < sizeof(T) * BitsPerByte, "Sanity"); - assert(lz > 0, "Will overflow"); return T(1) << (sizeof(T) * BitsPerByte - lz); } -// Helper function to get the maximum positive value. Implemented here -// since using std::numeric_limits<T>::max() seems problematic on some -// platforms. - -template <typename T> T max_value() { - if (IsSigned<T>::value) { - // Highest positive power of two expressible in the type - uint64_t val = static_cast<T>(1) << (sizeof(T) * BitsPerByte - 2); - // Fill lower bits with ones - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - if (sizeof(T) >= 2) val |= val >> 8; - if (sizeof(T) >= 4) val |= val >> 16; - if (sizeof(T) == 8) val |= val >> 32; - return (T)val; - } else { - return ~(static_cast<T>(0)); - } -} - // Calculate the next power of two greater than the given value. - -// Accepts 0 (returns 1), overflows with assert if value is larger than -// or equal to 2^31 (signed: 2^30) or 2^63 (signed: 2^62), for 32- -// and 64-bit integers, respectively -template <typename T> +// precondition: if signed, value >= 0. +// precondition: value < maximum power of two representable by T. +template <typename T, ENABLE_IF(std::is_integral<T>::value)> inline T next_power_of_2(T value) { - assert(value != max_value<T>(), "Overflow"); + assert(value < std::numeric_limits<T>::max(), "Overflow"); return round_up_power_of_2(value + 1); } diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index b49984de8d9..f767cdad803 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -144,8 +144,7 @@ static void print_bug_submit_message(outputStream *out, Thread *thread) { // provider of that code. if (thread && thread->is_Java_thread() && !thread->is_hidden_from_external_view()) { - JavaThread* jt = (JavaThread*)thread; - if (jt->thread_state() == _thread_in_native) { + if (thread->as_Java_thread()->thread_state() == _thread_in_native) { out->print_cr("# The crash happened outside the Java Virtual Machine in native code.\n# See problematic frame for where to report the bug."); } } @@ -259,7 +258,7 @@ void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, char* bu break; } if (fr.is_java_frame() || fr.is_native_frame() || fr.is_runtime_frame()) { - RegisterMap map((JavaThread*)t, false); // No update + RegisterMap map(t->as_Java_thread(), false); // No update fr = fr.sender(&map); } else { // is_first_C_frame() does only simple checks for frame pointer, @@ -743,7 +742,7 @@ void VMError::report(outputStream* st, bool _verbose) { STEP("printing Java stack") if (_verbose && _thread && _thread->is_Java_thread()) { - print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf)); + print_stack_trace(st, _thread->as_Java_thread(), buf, sizeof(buf)); } STEP("printing target Java thread stack") diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 1fabad43738..cdd45808bf2 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -4424,17 +4424,22 @@ public ClassDesc[] permittedSubclasses() { } /** - * * {@preview Associated with sealed classes, a preview feature of the Java language. + * {@preview Associated with sealed classes, a preview feature of the Java language. * * This method is associated with <i>sealed classes</i>, a preview * feature of the Java language. Preview features * may be removed in a future release, or upgraded to permanent * features of the Java language.} * - * Returns {@code true} if and only if this {@code Class} object represents a sealed class or interface. - * If this {@code Class} object represents a primitive type, {@code void}, or an array type, this method returns + * Returns {@code true} if and only if this {@code Class} object represents + * a sealed class or interface. If this {@code Class} object represents a + * primitive type, {@code void}, or an array type, this method returns * {@code false}. * + * @apiNote + * This method reports on a distinct concept of sealing from + * {@link Package#isSealed() Package::isSealed}. + * * @return {@code true} if and only if this {@code Class} object represents a sealed class or interface. * * @jls 8.1 Class Declarations diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index aff4857e410..0b870c23be2 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -2714,6 +2714,17 @@ private boolean trySetObjectField(String name, Object obj) { offset = unsafe.objectFieldOffset(k, name); return unsafe.compareAndSetReference(this, offset, null, obj); } + + /** + * Called by the VM, during -Xshare:dump + */ + private void resetArchivedStates() { + parallelLockMap.clear(); + packages.clear(); + package2certs.clear(); + classes.clear(); + classLoaderValueMap = null; + } } /* diff --git a/src/java.base/share/classes/java/lang/ClassValue.java b/src/java.base/share/classes/java/lang/ClassValue.java index 1b4c114a8ac..beb07bb2782 100644 --- a/src/java.base/share/classes/java/lang/ClassValue.java +++ b/src/java.base/share/classes/java/lang/ClassValue.java @@ -29,6 +29,8 @@ import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; +import jdk.internal.misc.Unsafe; + import static java.lang.ClassValue.ClassValueMap.probeHomeLocation; import static java.lang.ClassValue.ClassValueMap.probeBackupLocations; @@ -369,12 +371,22 @@ private static ClassValueMap getMap(Class<?> type) { } private static final Object CRITICAL_SECTION = new Object(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static ClassValueMap initializeMap(Class<?> type) { ClassValueMap map; synchronized (CRITICAL_SECTION) { // private object to avoid deadlocks // happens about once per type - if ((map = type.classValueMap) == null) - type.classValueMap = map = new ClassValueMap(); + if ((map = type.classValueMap) == null) { + map = new ClassValueMap(); + // Place a Store fence after construction and before publishing to emulate + // ClassValueMap containing final fields. This ensures it can be + // published safely in the non-volatile field Class.classValueMap, + // since stores to the fields of ClassValueMap will not be reordered + // to occur after the store to the field type.classValueMap + UNSAFE.storeFence(); + + type.classValueMap = map; + } } return map; } diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index 119621c9b16..3d5734f7a91 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -55,6 +55,7 @@ import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.BootLoader; import jdk.internal.loader.ClassLoaders; +import jdk.internal.misc.VM; import jdk.internal.module.IllegalAccessLogger; import jdk.internal.module.ModuleLoaderMap; import jdk.internal.module.ServicesCatalog; @@ -246,12 +247,55 @@ public ModuleLayer getLayer() { // -- // special Module to mean "all unnamed modules" - private static final Module ALL_UNNAMED_MODULE = new Module(null); - private static final Set<Module> ALL_UNNAMED_MODULE_SET = Set.of(ALL_UNNAMED_MODULE); + private static final Module ALL_UNNAMED_MODULE; + private static final Set<Module> ALL_UNNAMED_MODULE_SET; // special Module to mean "everyone" - private static final Module EVERYONE_MODULE = new Module(null); - private static final Set<Module> EVERYONE_SET = Set.of(EVERYONE_MODULE); + private static final Module EVERYONE_MODULE; + private static final Set<Module> EVERYONE_SET; + + private static class ArchivedData { + private static ArchivedData archivedData; + private final Module allUnnamedModule; + private final Set<Module> allUnnamedModules; + private final Module everyoneModule; + private final Set<Module> everyoneSet; + + private ArchivedData() { + this.allUnnamedModule = ALL_UNNAMED_MODULE; + this.allUnnamedModules = ALL_UNNAMED_MODULE_SET; + this.everyoneModule = EVERYONE_MODULE; + this.everyoneSet = EVERYONE_SET; + } + + static void archive() { + archivedData = new ArchivedData(); + } + + static ArchivedData get() { + return archivedData; + } + + static { + VM.initializeFromArchive(ArchivedData.class); + } + } + + static { + ArchivedData archivedData = ArchivedData.get(); + if (archivedData != null) { + ALL_UNNAMED_MODULE = archivedData.allUnnamedModule; + ALL_UNNAMED_MODULE_SET = archivedData.allUnnamedModules; + EVERYONE_MODULE = archivedData.everyoneModule; + EVERYONE_SET = archivedData.everyoneSet; + } else { + ALL_UNNAMED_MODULE = new Module(null); + ALL_UNNAMED_MODULE_SET = Set.of(ALL_UNNAMED_MODULE); + EVERYONE_MODULE = new Module(null); + EVERYONE_SET = Set.of(EVERYONE_MODULE); + ArchivedData.archive(); + } + } /** * The holder of data structures to support readability, exports, and diff --git a/src/java.base/share/classes/java/lang/Package.java b/src/java.base/share/classes/java/lang/Package.java index 934bc0ed992..98e14ae7be6 100644 --- a/src/java.base/share/classes/java/lang/Package.java +++ b/src/java.base/share/classes/java/lang/Package.java @@ -223,6 +223,10 @@ public String getImplementationVendor() { /** * Returns true if this package is sealed. * + * @apiNote + * This method reports on a distinct concept of sealing from + * {@link Class#isSealed() Class::isSealed}. + * * @return true if the package is sealed, false otherwise */ public boolean isSealed() { diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 4bc6f30d473..b8ab97f008c 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -2248,6 +2248,9 @@ public boolean isReflectivelyOpened(Module m, String pn, Module other) { public ServicesCatalog getServicesCatalog(ModuleLayer layer) { return layer.getServicesCatalog(); } + public void bindToLoader(ModuleLayer layer, ClassLoader loader) { + layer.bindToLoader(loader); + } public Stream<ModuleLayer> layers(ModuleLayer layer) { return layer.layers(); } diff --git a/src/java.base/share/classes/java/lang/runtime/PatternCarriers.java b/src/java.base/share/classes/java/lang/runtime/PatternCarriers.java deleted file mode 100755 index d6231933031..00000000000 --- a/src/java.base/share/classes/java/lang/runtime/PatternCarriers.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang.runtime; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.Arrays; -import java.util.List; - -/** - * PatternCarriers - */ -class PatternCarriers { - - private static final CarrierFactory factory = CarrierFactories.DUMB; - - interface CarrierFactory { - MethodHandle constructor(MethodType methodType); - MethodHandle component(MethodType methodType, int component); - } - - static class DumbCarrier { - private final Object[] args; - - DumbCarrier(Object... args) { - this.args = args.clone(); - } - - Object get(int i) { - return args[i]; - } - } - - enum CarrierFactories implements CarrierFactory { - DUMB { - private final MethodHandle CARRIER_CTOR; - private final MethodHandle CARRIER_GET; - - { - try { - CARRIER_CTOR = MethodHandles.lookup().findConstructor(DumbCarrier.class, MethodType.methodType(void.class, Object[].class)); - CARRIER_GET = MethodHandles.lookup().findVirtual(DumbCarrier.class, "get", MethodType.methodType(Object.class, int.class)); - } - catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - - @Override - public MethodHandle constructor(MethodType methodType) { - return CARRIER_CTOR.asType(methodType.changeReturnType(Object.class)); - } - - @Override - public MethodHandle component(MethodType methodType, int component) { - return MethodHandles.insertArguments(CARRIER_GET, 1, component) - .asType(MethodType.methodType(methodType.parameterType(component), Object.class)); - } - }, - DUMB_SINGLE { - // An optimization of DUMB, where we use the value itself as carrier when there is only one value - - @Override - public MethodHandle constructor(MethodType methodType) { - return methodType.parameterCount() == 1 ? MethodHandles.identity(methodType.parameterType(0)) : DUMB.constructor(methodType); - } - - @Override - public MethodHandle component(MethodType methodType, int component) { - return methodType.parameterCount() == 1 ? MethodHandles.identity(methodType.parameterType(0)) : DUMB.component(methodType, component); - } - } - } - - /** - * Returns a method handle with the given method type that instantiates - * a new carrier object. - * - * @param methodType the types of the carrier elements - * @return the carrier factory - */ - public static MethodHandle carrierFactory(MethodType methodType) { - return factory.constructor(methodType); - } - - /** - * Returns a method handle that accepts a carrier and returns the i'th component - * - * @param methodType the type of the carrier elements - * @param i the index of the component - * @return the component method handle - */ - public static MethodHandle carrierComponent(MethodType methodType, int i) { - return factory.component(methodType, i); - } - - /** - * Return all the components method handles for a carrier - * @param methodType the type of the carrier elements - * @return the component method handles - */ - public static List<MethodHandle> carrierComponents(MethodType methodType) { - MethodHandle[] components = new MethodHandle[methodType.parameterCount()]; - Arrays.setAll(components, i -> factory.component(methodType, i)); - return List.of(components); - } -} diff --git a/src/java.base/share/classes/java/lang/runtime/PatternHandle.java b/src/java.base/share/classes/java/lang/runtime/PatternHandle.java deleted file mode 100755 index 907b9ebd7aa..00000000000 --- a/src/java.base/share/classes/java/lang/runtime/PatternHandle.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang.runtime; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; -import java.util.List; - -/** - * Runtime object for low-level implementation of <em>pattern matching</em>. A - * {@linkplain PatternHandle} exposes functionality for determining if a target - * matches the pattern, and if so, for conditionally extracting the resulting - * bindings. - * - * <p>A {@linkplain PatternHandle} is parameterized by a <em>target type</em> - * and zero or more <em>binding variable types</em>. The target type (denoted - * {@code T}) is the type against which the pattern can be applied (often a - * broad type such as {@link Object}, but need not be), and the binding variable - * types (denoted {@code B*}) are the types of the binding variables that are - * produced by a successful match. These types are combined into a type - * <em>descriptor</em>, accessed via {@link #descriptor()}, where the return - * type of the descriptor is the target type, and the parameter types of the - * descriptor are the binding variable types. - * - * <p>The behavior of a {@linkplain PatternHandle} is exposed via method - * handles. The method handle returned by {@link #tryMatch()} is applied to the - * target to be tested, and returns an opaque result of type {@code Object}. If - * the result is {@code null}, the match has failed; if is non-null, it has - * succeeded, and the result can be used as input to the method handles returned - * by {@link #components()} or {@link #component(int)} to retrieve specific - * binding variables. - * - * <p>The class {@link PatternHandles} contains numerous factories and - * combinators for {@linkplain PatternHandle}s, including {@link - * PatternHandles#adaptTarget(PatternHandle, Class)} which can be used to adapt - * a pattern handle from one target type to another (such as widening the set of - * types against which it can be applied.) - * - * <p>{@linkplain PatternHandle} implementations must be <a - * href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a> - * classes. - */ -public interface PatternHandle { - - /** - * Returns a method handle that attempts to perform the pattern match - * described by this pattern handle. It will have type {@code (T)Object}, - * where {@code T} is the target type of the extractor. It accepts the - * target to be matched, and returns a non-null opaque carrier of type - * {@link Object} if the match succeeds, or {@code null} if it fails. - * - * @return the {@code tryMatch} method handle - */ - MethodHandle tryMatch(); - - /** - * Returns a method handle that extracts a component from a successful - * match. It will have type {@code (Object)Bi}, where {@code Bi} is the - * type of the corresponding binding variable, and will take the match - * carrier and return the corresponding binding variable. - * - * @param i the index of the component - * @return the component method handle - * @throws IndexOutOfBoundsException if {@code i} does not correspond to the - * index of a binding variable of this - * pattern - */ - MethodHandle component(int i); - - /** - * Returns all the component method handles for this pattern as a {@link - * List}. - * - * @return the component method handles - */ - List<MethodHandle> components(); - - /** - * Returns the descriptor for this pattern. The parameter types of the - * descriptor are the types of the binding variables, and the return type is - * the target type. - * - * @return the pattern type descriptor - */ - MethodType descriptor(); -} diff --git a/src/java.base/share/classes/java/lang/runtime/PatternHandles.java b/src/java.base/share/classes/java/lang/runtime/PatternHandles.java deleted file mode 100755 index ee028b390f5..00000000000 --- a/src/java.base/share/classes/java/lang/runtime/PatternHandles.java +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang.runtime; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.List; -import java.util.Objects; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import sun.invoke.util.BytecodeName; -import sun.invoke.util.Wrapper; - -import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface; -import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic; -import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual; -import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial; -import static java.util.Objects.requireNonNull; - -/** - * Factories and combinators for {@link PatternHandle}s. - */ -public final class PatternHandles { - private static final MethodHandle[] EMPTY_MH_ARRAY = new MethodHandle[0]; - private static final Object NULL_SENTINEL = new Object(); - - private PatternHandles() { - } - - // Factories - - /** - * Returns a {@linkplain PatternHandle} for a <em>type pattern</em>, which - * matches all non-null instances of the match type, with a single binding - * variable which is the target cast to the match type. The target type of - * the resulting pattern is the match type; if a broader target type is - * desired, use {@link #ofType(Class, Class)} or adapt the resulting pattern - * handle with {@link #adaptTarget(PatternHandle, Class)}. - * - * @param matchType the type to match against - * @return a pattern handle for a type pattern - */ - public static PatternHandle ofType(Class<?> matchType) { - requireNonNull(matchType); - MethodType descriptor = MethodType.methodType(matchType, matchType); - MethodHandle component = MethodHandles.identity(matchType); - MethodHandle tryMatch - = matchType.isPrimitive() - ? MethodHandles.identity(matchType) - : MH_OF_TYPE_TRY_MATCH.bindTo(matchType).asType(descriptor); - - return new PatternHandleImpl(descriptor, tryMatch, List.of(component)); - } - - /** - * Returns a {@linkplain PatternHandle} for a <em>type pattern</em>, which - * matches all non-null instances of the match type, with a single binding - * variable which is the target cast to the match type. The target type of - * the resulting pattern is the {@code targetType}. - * - * @param matchType the type to match against - * @param targetType the desired target type for the resulting pattern - * handle - * @return a pattern handle for a type pattern - * @throws IllegalArgumentException if the provided match type and target - * type are not compatible - */ - public static PatternHandle ofType(Class<?> matchType, Class<?> targetType) { - return adaptTarget(ofType(matchType), targetType); - } - - /** - * Returns a {@linkplain PatternHandle} for a <em>nullable type - * pattern</em>, which matches all instances of the match type, plus {@code - * null}, with a single binding variable which is the target cast to the - * match type. The target type of the resulting pattern is the match type; - * if a broader target type is desired, use {@link #ofType(Class, Class)} or - * adapt the resulting pattern handle with {@link #adaptTarget(PatternHandle, - * Class)}. - * - * @param matchType the type to match against - * @return a pattern handle for a nullable type pattern - */ - public static PatternHandle ofTypeNullable(Class<?> matchType) { - requireNonNull(matchType); - MethodType descriptor = MethodType.methodType(matchType, matchType); - MethodHandle component = MH_OF_TYPE_NULLABLE_COMPONENT - .asType(MethodType.methodType(matchType, Object.class)); - MethodHandle tryMatch - = matchType.isPrimitive() - ? MethodHandles.identity(matchType) - : MH_OF_TYPE_NULLABLE_TRY_MATCH.bindTo(matchType) - .asType(MethodType.methodType(Object.class, matchType)); - - return new PatternHandleImpl(descriptor, tryMatch, List.of(component)); - } - - /** - * Returns a {@linkplain PatternHandle} for a <em>nullable type - * pattern</em>, which matches all instances of the match type, plus {@code - * null}, with a single binding variable which is the target cast to the - * match type. The target type of the resulting pattern is the {@code - * targetType}. - * - * @param matchType the type to match against - * @param targetType the desired target type for the resulting pattern - * handle - * @return a pattern handle for a nullable type pattern - * @throws IllegalArgumentException if the provided match type and target - * type are not compatible - */ - public static PatternHandle ofTypeNullable(Class<?> matchType, Class<?> targetType) { - return adaptTarget(ofTypeNullable(matchType), targetType); - } - - /** - * Returns a {@linkplain PatternHandle} for a <em>constant pattern</em>, - * which matches all instances that are {@link Object#equals(Object)} to - * the specified constant. The resulting pattern has no binding variables. - * If the constant is {@code null}, the target type of the pattern is - * {@link Object}, otherwise it is the result of {@code Object::getClass} - * on the constant. - * - * <p>TODO: restrict type of constant to String, boxes, and enums? - * - * @param o the constant - * @return a pattern handle for a constant pattern - */ - public static PatternHandle ofConstant(Object o) { - Class<?> type = o == null ? Object.class : o.getClass(); - MethodHandle match = partialize(MethodHandles.dropArguments(MethodHandles.constant(Object.class, Boolean.TRUE), 0, type), - MethodHandles.insertArguments(MH_OBJECTS_EQUAL, 0, o) - .asType(MethodType.methodType(boolean.class, type))); - return new PatternHandleImpl(MethodType.methodType(type), match, List.of()); - } - - /** - * Returns a {@linkplain PatternHandle} for a <em>constant pattern</em>, - * which matches all instances that are {@link Object#equals(Object)} to - * the specified constant. The resulting pattern has no binding variables. - * The target type of the pattern is {@code targetType}. - * - * @param o the constant - * @param targetType the target type for the pattern - * @return a pattern handle for a constant pattern - * @throws IllegalArgumentException if the type of the constant and the - * target type are not compatible - */ - public static PatternHandle ofConstant(Object o, Class<?> targetType) { - return adaptTarget(ofConstant(0), targetType); - } - - // @@@ Primitive constant patterns - - /** - * Returns a {@linkplain PatternHandle} for decomposing a target into its - * components. It matches all non-null instances of the specified target - * type, and extracts one binding variable for each component specified in - * the {@code components} argument. The method handles in {@code components} - * must be of type {@code (T)Bi} where T is the target type of the pattern - * and Bi is the i'th binding variable. The components are extracted - * <em>lazily</em> -- when the component method handle is invoked by the - * client -- rather than when the {@code tryMatch} method handle is invoked. - * - * @param targetType The type of the match target - * @param components The component method handles - * @return a pattern handle for a decomposition pattern - */ - public static PatternHandle ofLazyProjection(Class<?> targetType, - MethodHandle... components) { - requireNonNull(targetType); - requireNonNull(components); - return new PatternHandleImpl(descriptor(targetType, components), - MethodHandles.identity(targetType), - List.of(components)); - } - - /** - * Returns a {@linkplain PatternHandle} for decomposing a target into its - * components. It matches all non-null instances of the specified target - * type, and extracts one binding variable for each component specified in - * the {@code components} argument. The method handles in {@code components} - * must be of type {@code (T)Bi} where T is the target type of the pattern - * and Bi is the i'th binding variable. The components are extracted - * <em>eagerly</em> -- at the time the {@code tryMatch} method handle is - * invoked. - * - * @param targetType The type of the match target - * @param components The component method handles - * @return a pattern handle for a decomposition pattern - */ - public static PatternHandle ofEagerProjection(Class<?> targetType, - MethodHandle... components) { - requireNonNull(targetType); - requireNonNull(components); - MethodType descriptor = descriptor(targetType, components); - return new PatternHandleImpl(descriptor, - carrierTryExtract(descriptor, components), - PatternCarriers.carrierComponents(descriptor)); - } - - /** - * Returns a {@linkplain PatternHandle} that delegates matching and - * extraction to another method handle. The target type of the pattern is - * the return type of the {@code descriptor}, and the binding variable types - * are the parameter types of the {@code descriptor}. The {@code tryMatch} - * method handle will invoke the specified {@code digester} method handle - * with the target, as well as a method handle whose parameter types are - * the binding variable types and whose return type is some type {@code C}. - * For a successful match, the digester method should invoke this method - * handle with the extracted bindings, and return the result; for an - * unsuccessful match, it should return {@code null}. - * - * @param descriptor the type descriptor of the pattern - * @param digester the digester method handle - * @return a pattern handle implementing the pattern - */ - public static PatternHandle ofImperative(MethodType descriptor, - MethodHandle digester) { - Class<?> targetType = descriptor.returnType(); - return new PatternHandleImpl(descriptor, - partialize(MethodHandles.insertArguments(digester, - 1, PatternCarriers.carrierFactory(descriptor)), - MH_OBJECTS_NONNULL.asType(MH_OBJECTS_NONNULL.type().changeParameterType(0, targetType))), - PatternCarriers.carrierComponents(descriptor)); - } - - /** - * Compose a pattern handle with a method handle that receives the bindings. The - * argument types of the target method must match those of the binding - * types. The resulting method handle accepts an argument which is the - * target type of the pattern, and which returns either {@code null} - * if the match fails or the result of the target method handle - * if the match succeeds. - * - * @param patternHandle the pattern handle - * @param target a method handle that receives the bindings and - * produces a result - * @return the composed method handle - */ - public static MethodHandle compose(PatternHandle patternHandle, MethodHandle target) { - int count = patternHandle.descriptor().parameterCount(); - MethodHandle[] components = patternHandle.components().toArray(EMPTY_MH_ARRAY); - Class<?> carrierType = patternHandle.tryMatch().type().returnType(); - Class<?> resultType = target.type().returnType(); - - MethodHandle mh = MethodHandles.filterArguments(target, 0, components); - mh = MethodHandles.permuteArguments(mh, MethodType.methodType(resultType, carrierType), new int[count]); - mh = MethodHandles.guardWithTest(MH_OBJECTS_NONNULL.asType(MethodType.methodType(boolean.class, carrierType)), - mh, - MethodHandles.dropArguments(MethodHandles.constant(resultType, null), 0, carrierType)); - mh = MethodHandles.filterArguments(mh, 0, patternHandle.tryMatch()); - return mh; - } - - // Combinators - - /** - * Adapts a {@linkplain PatternHandle} to a new target type. If the - * pattern is of primitive type, it may be adapted to a supertype of its - * corresponding box type; if it is of reference type, it may be widened - * or narrowed to another reference type. - * - * @param pattern the pattern - * @param newTarget the new target type - * @return the adapted pattern - * @throws IllegalArgumentException if the new target type is not compatible - * with the target type of the pattern - */ - public static PatternHandle adaptTarget(PatternHandle pattern, Class<?> newTarget) { - Class<?> oldTarget = pattern.descriptor().returnType(); - if (oldTarget == newTarget) - return pattern; - - Class<?> oldWrapperType = oldTarget.isPrimitive() ? Wrapper.forPrimitiveType(oldTarget).wrapperType() : null; - MethodType guardType = MethodType.methodType(boolean.class, newTarget); - MethodHandle guard; - if (oldWrapperType != null && newTarget.isAssignableFrom(oldWrapperType)) { - // Primitive boxing (with optional widening) - guard = MH_PRIMITIVE_ADAPT_HELPER.bindTo(oldWrapperType).asType(guardType); - } - else if (newTarget.isAssignableFrom(oldTarget) || oldTarget.isAssignableFrom(newTarget)) { - // reference narrowing or widening - guard = MH_REFERENCE_ADAPT_HELPER.bindTo(oldTarget).asType(guardType); - } - else { - throw new IllegalArgumentException(String.format("New target type %s not compatible with old target type %s", - newTarget, oldTarget)); - } - - MethodType tryMatchType = pattern.tryMatch().type().changeParameterType(0, newTarget); - return new PatternHandleImpl(pattern.descriptor().changeReturnType(newTarget), - partialize(pattern.tryMatch().asType(tryMatchType), - guard), - pattern.components()); - } - - /** - * Returns a {@linkplain PatternHandle} that implements the same pattern - * as another {@linkplain PatternHandle}, but potentially with fewer binding - * variables. - * - * @param pattern the original pattern - * @param positions the indexes of the binding variables to drop - * @return the new pattern - * @throws IndexOutOfBoundsException if any of the indexes are out of range - * for the bindings of the original pattern - */ - public static PatternHandle dropBindings(PatternHandle pattern, int... positions) { - MethodHandle[] mhs = pattern.components().toArray(EMPTY_MH_ARRAY); - for (int position : positions) - mhs[position] = null; - mhs = Stream.of(mhs).filter(Objects::nonNull).toArray(MethodHandle[]::new); - return new PatternHandleImpl(descriptor(pattern.descriptor().returnType(), mhs), pattern.tryMatch(), List.of(mhs)); - } - - /** - * Returns a {@linkplain PatternHandle} for a <em>nested</em> pattern. A - * nested pattern first matches the target to the outer pattern, and if - * it matches successfully, then matches the resulting bindings to the inner - * patterns. The resulting pattern matches if the outer pattern matches - * the target, and the bindings match the appropriate inner patterns. The - * target type of the nested pattern is the same as the target type of - * the outer pattern. The bindings are the bindings for the outer pattern, - * followed by the concatenation of the bindings for the inner patterns. - * - * @param outer The outer pattern - * @param inners The inner patterns, which can be null if no nested pattern - * for the corresponding binding is desired - * @return the nested pattern - */ - public static PatternHandle nested(PatternHandle outer, PatternHandle... inners) { - PatternHandle[] patternHandles = inners.clone(); - int outerCount = outer.descriptor().parameterCount(); - Class<?> outerCarrierType = outer.tryMatch().type().returnType(); - - // Adapt inners to types of outer bindings - for (int i = 0; i < patternHandles.length; i++) { - PatternHandle patternHandle = patternHandles[i]; - if (patternHandle.descriptor().returnType() != outer.descriptor().parameterType(i)) - patternHandles[i] = adaptTarget(patternHandle, outer.descriptor().parameterType(i)); - } - - int[] innerPositions = IntStream.range(0, patternHandles.length) - .filter(i -> patternHandles[i] != null) - .toArray(); - MethodHandle[] innerComponents = Stream.of(patternHandles) - .filter(Objects::nonNull) - .map(PatternHandle::components) - .flatMap(List::stream) - .toArray(MethodHandle[]::new); - MethodHandle[] innerTryMatches = Stream.of(patternHandles) - .filter(Objects::nonNull) - .map(PatternHandle::tryMatch) - .toArray(MethodHandle[]::new); - Class<?>[] innerCarriers = Stream.of(patternHandles) - .filter(Objects::nonNull) - .map(e -> e.tryMatch().type().returnType()) - .toArray(Class[]::new); - Class<?>[] innerTypes = Stream.of(innerComponents) - .map(mh -> mh.type().returnType()) - .toArray(Class[]::new); - - MethodType descriptor = outer.descriptor().appendParameterTypes(innerTypes); - - MethodHandle mh = PatternCarriers.carrierFactory(descriptor); - mh = MethodHandles.filterArguments(mh, outerCount, innerComponents); - int[] spreadInnerCarriers = new int[outerCount + innerComponents.length]; - for (int i = 0; i < outerCount; i++) - spreadInnerCarriers[i] = i; - int k = outerCount; - int j = 0; - for (PatternHandle e : patternHandles) { - if (e == null) - continue; - for (int i = 0; i < e.descriptor().parameterCount(); i++) - spreadInnerCarriers[k++] = outerCount + j; - j++; - } - MethodType spreadInnerCarriersMT = outer.descriptor() - .appendParameterTypes(innerCarriers) - .changeReturnType(mh.type().returnType()); - mh = MethodHandles.permuteArguments(mh, spreadInnerCarriersMT, spreadInnerCarriers); - for (int position : innerPositions) - mh = bailIfNthNull(mh, outerCount + position); - mh = MethodHandles.filterArguments(mh, outerCount, innerTryMatches); - int[] spreadNestedCarrier = new int[outerCount + innerPositions.length]; - for (int i = 0; i < outerCount; i++) - spreadNestedCarrier[i] = i; - for (int i = 0; i < innerPositions.length; i++) - spreadNestedCarrier[outerCount + i] = innerPositions[i]; - mh = MethodHandles.permuteArguments(mh, outer.descriptor().changeReturnType(mh.type().returnType()), - spreadNestedCarrier); - mh = MethodHandles.filterArguments(mh, 0, outer.components().toArray(EMPTY_MH_ARRAY)); - mh = MethodHandles.permuteArguments(mh, MethodType.methodType(mh.type().returnType(), outerCarrierType), - new int[outerCount]); - mh = bailIfNthNull(mh, 0); - mh = MethodHandles.filterArguments(mh, 0, outer.tryMatch()); - - MethodHandle tryExtract = mh; - - return new PatternHandleImpl(descriptor, tryExtract, PatternCarriers.carrierComponents(descriptor)); - } - - // @@@ AND combinator - // @@@ GUARDED combinator - - // Bootstraps - - /** - * Bootstrap method for creating a lazy projection pattern, as per - * {@link #ofLazyProjection(Class, MethodHandle...)}, - * suitable for use as a {@code constantdynamic} bootstrap. Suitable for use - * by compilers which are generating implementations of patterns whose bindings - * are independently derived from the target. - * - * @apiNote When the "bootstrap consolidation" project completes, this method - * can go away and {@link #ofLazyProjection(Class, MethodHandle...)} - * can be used directly as a condy bootstrap. - * - * @param lookup ignored - * @param constantName ignored - * @param constantType Must be {@code PatternHandle.class} - * @param targetType the target type of the pattern - * @param components the pattern components - * @return a pattern handle - * @throws Throwable doc - */ - public static PatternHandle ofLazyProjection(MethodHandles.Lookup lookup, - String constantName, - Class<?> constantType, - Class<?> targetType, - MethodHandle... components) - throws Throwable { - return ofLazyProjection(targetType, components); - } - - /** - * Bootstrap method for finding named {@link PatternHandle}s that have been - * compiled according to the scheme outlined in JLS ?.?. - * - * @param lookup the lookup context - * @param constantName ignored - * @param constantType must be {@code PatternHandle.class} - * @param owner the class containing the pattern - * @param descriptor the extractor descriptor - * @param name the extractor name - * @param refKind the kind of method - * @return the extractor - * @throws Throwable if something went wrong - */ - public static PatternHandle ofNamed(MethodHandles.Lookup lookup, - String constantName, - Class<PatternHandle> constantType, - Class<?> owner, - MethodType descriptor, - String name, - int refKind) throws Throwable { - String dd = descriptor.toMethodDescriptorString(); - String memberName = String.format("$pattern$%s$%s", - (refKind == REF_newInvokeSpecial ? owner.getSimpleName() : name), - dd.substring(0, dd.indexOf(')') + 1)); - String patternMethodName = BytecodeName.toBytecodeName(memberName); - MethodType factoryDesc = MethodType.methodType(PatternHandle.class); - MethodHandle mh; - switch (refKind) { - case REF_invokeStatic: - case REF_newInvokeSpecial: - mh = lookup.findStatic(owner, patternMethodName, factoryDesc); - break; - case REF_invokeVirtual: - case REF_invokeInterface: - mh = lookup.findVirtual(owner, patternMethodName, factoryDesc); - break; - default: - throw new IllegalAccessException(Integer.toString(refKind)); - } - - return (PatternHandle) mh.invoke(); - } - - /** - * Bootstrap method for extracting the {@code tryMatch} method handle from a - * {@linkplain PatternHandle}. - * - * @apiNote When the "bootstrap consolidation" project completes, this method - * can go away and {@link PatternHandle#tryMatch()} can be used directly as - * a condy bootstrap. - * - * @param lookup ignored - * @param constantName ignored - * @param constantType Must be {@code MethodHandle.class} - * @param patternHandle the pattern handle - * @return the {@code tryMatch} method handle - */ - public static MethodHandle tryMatch(MethodHandles.Lookup lookup, String constantName, Class<MethodHandle> constantType, - PatternHandle patternHandle) { - return patternHandle.tryMatch(); - } - - /** - * Bootstrap method for extracting a {@code component} method handle from a - * {@linkplain PatternHandle}. - * - * @apiNote When the "bootstrap consolidation" project completes, this method - * can go away and {@link PatternHandle#component(int)} ()} can be used directly as - * a condy bootstrap. - * - * @param lookup ignored - * @param constantName ignored - * @param constantType Must be {@code MethodHandle.class} - * @param patternHandle the pattern - * @param i the index of the desired component - * @return the component method handle - */ - public static MethodHandle component(MethodHandles.Lookup lookup, - String constantName, - Class<MethodHandle> constantType, - PatternHandle patternHandle, int i) { - return patternHandle.component(i); - } - - // Helpers - - /** - * Construct a partial method handle that uses the predicate as - * guardWithTest, which applies the target if the test succeeds, and returns - * null if the test fails. The resulting method handle is of the same type - * as the {@code target} method handle. - * - * @param target - * @param predicate - * @return - */ - private static MethodHandle partialize(MethodHandle target, - MethodHandle predicate) { - Class<?> targetType = target.type().parameterType(0); - Class<?> carrierType = target.type().returnType(); - return MethodHandles.guardWithTest(predicate, - target, - MethodHandles.dropArguments(MethodHandles.constant(carrierType, null), - 0, targetType)); - } - - /** - * Construct a method handle that delegates to target, unless the nth - * argument is null, in which case it returns null - */ - private static MethodHandle bailIfNthNull(MethodHandle target, int n) { - MethodHandle test = MH_OBJECTS_ISNULL - .asType(MH_OBJECTS_ISNULL.type() - .changeParameterType(0, target.type().parameterType(n))); - test = MethodHandles.permuteArguments(test, target.type().changeReturnType(boolean.class), n); - MethodHandle nullh = MethodHandles.dropArguments(MethodHandles.constant(target.type().returnType(), null), - 0, target.type().parameterArray()); - return MethodHandles.guardWithTest(test, nullh, target); - } - - private static MethodType descriptor(Class<?> targetType, MethodHandle[] components) { - Class<?>[] paramTypes = Stream.of(components) - .map(mh -> mh.type().returnType()) - .toArray(Class[]::new); - return MethodType.methodType(targetType, paramTypes); - } - - private static MethodHandle carrierTryExtract(MethodType descriptor, MethodHandle[] components) { - MethodHandle carrierFactory = PatternCarriers.carrierFactory(descriptor); - int[] reorder = new int[descriptor.parameterCount()]; // default value is what we want already - - Class<?> targetType = descriptor.returnType(); - return partialize(MethodHandles.permuteArguments(MethodHandles.filterArguments(carrierFactory, 0, components), - MethodType.methodType(carrierFactory.type().returnType(), targetType), - reorder), - MH_OBJECTS_NONNULL.asType(MH_OBJECTS_NONNULL.type().changeParameterType(0, targetType))); - } - - private static MethodHandle lookupStatic(Class<?> clazz, - String name, - Class<?> returnType, - Class<?>... paramTypes) - throws ExceptionInInitializerError { - try { - return MethodHandles.lookup().findStatic(clazz, name, MethodType.methodType(returnType, paramTypes)); - } - catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - - private static final MethodHandle MH_OF_TYPE_TRY_MATCH - = lookupStatic(PatternHandles.class, "ofTypeTryMatch", - Object.class, Class.class, Object.class); - private static final MethodHandle MH_OF_TYPE_NULLABLE_TRY_MATCH - = lookupStatic(PatternHandles.class, "ofTypeNullableTryMatch", - Object.class, Class.class, Object.class); - private static final MethodHandle MH_OF_TYPE_NULLABLE_COMPONENT - = lookupStatic(PatternHandles.class, "ofTypeNullableComponent", - Object.class, Object.class); - private static final MethodHandle MH_PRIMITIVE_ADAPT_HELPER - = lookupStatic(PatternHandles.class, "primitiveAdaptHelper", - boolean.class, Class.class, Object.class); - private static final MethodHandle MH_REFERENCE_ADAPT_HELPER - = lookupStatic(PatternHandles.class, "referenceAdaptHelper", - boolean.class, Class.class, Object.class); - private static final MethodHandle MH_OBJECTS_ISNULL - = lookupStatic(Objects.class, "isNull", - boolean.class, Object.class); - private static final MethodHandle MH_OBJECTS_NONNULL - = lookupStatic(Objects.class, "nonNull", - boolean.class, Object.class); - private static final MethodHandle MH_OBJECTS_EQUAL - = lookupStatic(Objects.class, "equals", - boolean.class, Object.class, Object.class); - - private static Object ofTypeTryMatch(Class<?> type, Object o) { - return o != null && type.isAssignableFrom(o.getClass()) - ? o - : null; - } - - private static Object ofTypeNullableTryMatch(Class<?> type, Object o) { - if (o == null) - return NULL_SENTINEL; - else if (type.isAssignableFrom(o.getClass())) - return o; - else - return null; - } - - private static Object ofTypeNullableComponent(Object o) { - return o == NULL_SENTINEL ? null : o; - } - - private static boolean primitiveAdaptHelper(Class<?> type, Object o) { - return o != null && type.isAssignableFrom(o.getClass()); - } - - private static boolean referenceAdaptHelper(Class<?> type, Object o) { - return o == null || type.isAssignableFrom(o.getClass()); - } - - /** - * Non-public implementation of {@link PatternHandle} - */ - private static class PatternHandleImpl implements PatternHandle { - - private final MethodType descriptor; - private final MethodHandle tryMatch; - private final List<MethodHandle> components; - - - /** - * Construct an {@link PatternHandle} from components Constraints: - - * output of tryMatch must match input of components - input of tryMatch - * must match descriptor - output of components must match descriptor - * - * @param descriptor The {@code descriptor} method type - * @param tryMatch The {@code tryMatch} method handle - * @param components The {@code component} method handles - */ - PatternHandleImpl(MethodType descriptor, MethodHandle tryMatch, - List<MethodHandle> components) { - MethodHandle[] componentsArray = components.toArray(new MethodHandle[0]); - Class<?> carrierType = tryMatch.type().returnType(); - if (descriptor.parameterCount() != componentsArray.length) - throw new IllegalArgumentException(String.format("MethodType %s arity should match component count %d", - descriptor, componentsArray.length)); - if (!descriptor.returnType().equals(tryMatch.type().parameterType(0))) - throw new IllegalArgumentException(String.format("Descriptor %s should match tryMatch input %s", - descriptor, tryMatch.type())); - for (int i = 0; i < componentsArray.length; i++) { - MethodType componentType = componentsArray[i].type(); - if (componentType.parameterCount() != 1 - || componentType.returnType().equals(void.class) - || !componentType.parameterType(0).equals(carrierType)) - throw new IllegalArgumentException("Invalid component descriptor " + componentType); - if (!componentType.returnType().equals(descriptor.parameterType(i))) - throw new IllegalArgumentException(String.format("Descriptor %s should match %d'th component %s", - descriptor, i, componentsArray[i])); - } - - if (!carrierType.equals(Object.class)) { - tryMatch = tryMatch.asType(tryMatch.type().changeReturnType(Object.class)); - for (int i = 0; i < componentsArray.length; i++) { - MethodHandle component = componentsArray[i]; - componentsArray[i] = component.asType(component.type().changeParameterType(0, Object.class)); - } - } - - this.descriptor = descriptor; - this.tryMatch = tryMatch; - this.components = List.of(componentsArray); - } - - @Override - public MethodHandle tryMatch() { - return tryMatch; - } - - @Override - public MethodHandle component(int i) { - return components.get(i); - } - - @Override - public List<MethodHandle> components() { - return components; - } - - @Override - public MethodType descriptor() { - return descriptor; - } - - } -} diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java deleted file mode 100755 index f68d82f6495..00000000000 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ /dev/null @@ -1,882 +0,0 @@ -/* - * 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 java.lang.runtime; - -import java.lang.invoke.CallSite; -import java.lang.invoke.ConstantCallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.stream.IntStream; -import java.util.stream.LongStream; -import java.util.stream.Stream; - -import static java.util.Objects.requireNonNull; - -/** - * Bootstrap methods for linking {@code invokedynamic} call sites that implement - * the selection functionality of the {@code switch} statement. The bootstraps - * take additional static arguments corresponding to the {@code case} labels - * of the {@code switch}, implicitly numbered sequentially from {@code [0..N)}. - * - * <p>The bootstrap call site accepts a single parameter of the type of the - * operand of the {@code switch}, and return an {@code int} that is the index of - * the matched {@code case} label, {@code -1} if the target is {@code null}, - * or {@code N} if the target is not null but matches no {@code case} label. - */ -public class SwitchBootstraps { - - // Shared INIT_HOOK for all switch call sites; looks the target method up in a map - private static final MethodHandle CONSTANT_INIT_HOOK; - private static final MethodHandle PATTERN_INIT_HOOK; - private static final MethodHandle TYPE_INIT_HOOK; - private static final MethodHandle PATTERN_SWITCH_METHOD; - private static final MethodHandle TYPE_SWITCH_METHOD; - private static final Map<Class<?>, MethodHandle> switchMethods = new ConcurrentHashMap<>(); - - private static final Set<Class<?>> BOOLEAN_TYPES - = Set.of(boolean.class, Boolean.class); - // Types that can be handled as int switches - private static final Set<Class<?>> INT_TYPES - = Set.of(int.class, short.class, byte.class, char.class, - Integer.class, Short.class, Byte.class, Character.class); - private static final Set<Class<?>> FLOAT_TYPES - = Set.of(float.class, Float.class); - private static final Set<Class<?>> LONG_TYPES - = Set.of(long.class, Long.class); - private static final Set<Class<?>> DOUBLE_TYPES - = Set.of(double.class, Double.class); - - private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - private static final Function<Class<?>, MethodHandle> lookupSwitchMethod = - new Function<>() { - @Override - public MethodHandle apply(Class<?> c) { - try { - Class<?> switchClass; - if (c == Enum.class) - switchClass = EnumSwitchCallSite.class; - else if (c == String.class) - switchClass = StringSwitchCallSite.class; - else if (BOOLEAN_TYPES.contains(c) || INT_TYPES.contains(c) || - FLOAT_TYPES.contains(c)) - switchClass = IntSwitchCallSite.class; - else if (LONG_TYPES.contains(c) || DOUBLE_TYPES.contains(c)) - switchClass = LongSwitchCallSite.class; - else if (c == Object.class) - switchClass = TypeSwitchCallSite.class; - else - throw new BootstrapMethodError("Invalid switch type: " + c); - - return LOOKUP.findVirtual(switchClass, "doSwitch", - MethodType.methodType(int.class, c)); - } - catch (ReflectiveOperationException e) { - throw new BootstrapMethodError("Invalid switch type: " + c); - } - } - }; - - static { - try { - CONSTANT_INIT_HOOK = LOOKUP.findStatic(SwitchBootstraps.class, "constantInitHook", - MethodType.methodType(MethodHandle.class, CallSite.class)); - PATTERN_INIT_HOOK = LOOKUP.findStatic(SwitchBootstraps.class, "patternInitHook", - MethodType.methodType(MethodHandle.class, CallSite.class)); - TYPE_INIT_HOOK = LOOKUP.findStatic(SwitchBootstraps.class, "typeInitHook", - MethodType.methodType(MethodHandle.class, CallSite.class)); - PATTERN_SWITCH_METHOD = LOOKUP.findVirtual(PatternSwitchCallSite.class, "doSwitch", - MethodType.methodType(PatternSwitchResult.class, Object.class)); - TYPE_SWITCH_METHOD = LOOKUP.findVirtual(TypeSwitchCallSite.class, "doSwitch", - MethodType.methodType(int.class, Object.class)); - } - catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - - private static<T extends CallSite> MethodHandle constantInitHook(T receiver) { - return switchMethods.computeIfAbsent(receiver.type().parameterType(0), lookupSwitchMethod) - .bindTo(receiver); - } - - private static<T extends CallSite> MethodHandle typeInitHook(T receiver) { - return TYPE_SWITCH_METHOD.bindTo(receiver); - } - - private static<T extends CallSite> MethodHandle patternInitHook(T receiver) { - return PATTERN_SWITCH_METHOD.bindTo(receiver); - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on a {@code boolean} or {@code Boolean}. - * The static arguments are a varargs array of {@code boolean} labels, - * - * <p>The results are undefined if the labels array contains duplicates. - * - * @implNote - * - * The implementation only enforces the requirement that the labels array - * be duplicate-free if system assertions are enabled. - * - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter which is - * {@code boolean} or {@code Boolean},and return {@code int}. - * When used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param booleanLabels boolean values corresponding to the case labels of the - * {@code switch} statement. - * @return the index into {@code booleanLabels} of the target value, if the target - * matches any of the labels, {@literal -1} if the target value is - * {@code null}, or {@code booleanLabels.length} if the target value does - * not match any of the labels. - * @throws NullPointerException if any required argument is null - * @throws IllegalArgumentException if the invocation type is not - * {@code (boolean)int} or {@code (Boolean)int} - * @throws Throwable if there is any error linking the call site - */ - public static CallSite booleanSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - boolean... booleanLabels) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || (!BOOLEAN_TYPES.contains(invocationType.parameterType(0)))) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(booleanLabels); - - int[] intLabels = IntStream.range(0, booleanLabels.length) - .map(i -> booleanLabels[i] ? 1 : 0) - .toArray(); - - assert IntStream.of(intLabels).distinct().count() == intLabels.length - : "switch labels are not distinct: " + Arrays.toString(booleanLabels); - - return new IntSwitchCallSite(invocationType, intLabels); - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on an {@code int}, {@code short}, {@code byte}, - * {@code char}, or one of their box types. The static arguments are a - * varargs array of {@code int} labels. - * - * <p>The results are undefined if the labels array contains duplicates. - * - * @implNote - * - * The implementation only enforces the requirement that the labels array - * be duplicate-free if system assertions are enabled. - * - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter which is - * one of the 32-bit or shorter primitive types, or - * one of their box types, and return {@code int}. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param intLabels integral values corresponding to the case labels of the - * {@code switch} statement. - * @return the index into {@code intLabels} of the target value, if the target - * matches any of the labels, {@literal -1} if the target value is - * {@code null}, or {@code intLabels.length} if the target value does - * not match any of the labels. - * @throws NullPointerException if any required argument is null - * @throws IllegalArgumentException if the invocation type is not - * {@code (T)int}, where {@code T} is one of the 32-bit or smaller integral - * primitive types, or one of their box types - * @throws Throwable if there is any error linking the call site - */ - public static CallSite intSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - int... intLabels) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || (!INT_TYPES.contains(invocationType.parameterType(0)))) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(intLabels); - - assert IntStream.of(intLabels).distinct().count() == intLabels.length - : "switch labels are not distinct: " + Arrays.toString(intLabels); - - return new IntSwitchCallSite(invocationType, intLabels); - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on an {@code float} or {@code Float}. - * The static arguments are a varargs array of {@code float} labels. - * - * <p>The results are undefined if the labels array contains duplicates - * according to {@link Float#floatToIntBits(float)}. - * - * @implNote - * - * The implementation only enforces the requirement that the labels array - * be duplicate-free if system assertions are enabled. - * - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter which is - * one of the 32-bit or shorter primitive types, or - * one of their box types, and return {@code int}. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param floatLabels float values corresponding to the case labels of the - * {@code switch} statement. - * @return the index into {@code floatLabels} of the target value, if the target - * matches any of the labels, {@literal -1} if the target value is - * {@code null}, or {@code floatLabels.length} if the target value does - * not match any of the labels. - * @throws NullPointerException if any required argument is null - * @throws IllegalArgumentException if the invocation type is not - * {@code (float)int} or {@code (Float)int} - * @throws Throwable if there is any error linking the call site - */ - public static CallSite floatSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - float... floatLabels) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || (!FLOAT_TYPES.contains(invocationType.parameterType(0)))) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(floatLabels); - - int[] intLabels = new int[floatLabels.length]; - for (int i=0; i<floatLabels.length; i++) - intLabels[i] = Float.floatToIntBits(floatLabels[i]); - - assert IntStream.of(intLabels).distinct().count() == intLabels.length - : "switch labels are not distinct: " + Arrays.toString(floatLabels); - - return new IntSwitchCallSite(invocationType, intLabels); - } - - static class IntSwitchCallSite extends ConstantCallSite { - private final int[] labels; - private final int[] indexes; - - IntSwitchCallSite(MethodType targetType, - int[] intLabels) throws Throwable { - super(targetType, CONSTANT_INIT_HOOK); - - // expensive way to index an array - indexes = IntStream.range(0, intLabels.length) - .boxed() - .sorted(Comparator.comparingInt(a -> intLabels[a])) - .mapToInt(Integer::intValue) - .toArray(); - labels = new int[indexes.length]; - for (int i=0; i<indexes.length; i++) - labels[i] = intLabels[indexes[i]]; - } - - int doSwitch(int target) { - int index = Arrays.binarySearch(labels, target); - return (index >= 0) ? indexes[index] : indexes.length; - } - - int doSwitch(boolean target) { - return doSwitch(target ? 1 : 0); - } - - int doSwitch(float target) { - return doSwitch(Float.floatToIntBits(target)); - } - - int doSwitch(short target) { - return doSwitch((int) target); - } - - int doSwitch(byte target) { - return doSwitch((int) target); - } - - int doSwitch(char target) { - return doSwitch((int) target); - } - - int doSwitch(Boolean target) { - return (target == null) ? -1 : doSwitch((boolean) target); - } - - int doSwitch(Integer target) { - return (target == null) ? -1 : doSwitch((int) target); - } - - int doSwitch(Float target) { - return (target == null) ? -1 : doSwitch((float) target); - } - - int doSwitch(Short target) { - return (target == null) ? -1 : doSwitch((int) target); - } - - int doSwitch(Character target) { - return (target == null) ? -1 : doSwitch((int) target); - } - - int doSwitch(Byte target) { - return (target == null) ? -1 : doSwitch((int) target); - } - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on a {@code long} or {@code Long}. - * The static arguments are a varargs array of {@code long} labels. - * - * <p>The results are undefined if the labels array contains duplicates. - * - * @implNote - * - * The implementation only enforces the requirement that the labels array - * be duplicate-free if system assertions are enabled. - * - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter which is - * one of the 32-bit or shorter primitive types, or - * one of their box types, and return {@code int}. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param longLabels long values corresponding to the case labels of the - * {@code switch} statement. - * @return the index into {@code longLabels} of the target value, if the target - * matches any of the labels, {@literal -1} if the target value is - * {@code null}, or {@code longLabels.length} if the target value does - * not match any of the labels. - * @throws NullPointerException if any required argument is null - * @throws IllegalArgumentException if the invocation type is not - * {@code (long)int} or {@code (Long)int} - * @throws Throwable if there is any error linking the call site - */ - public static CallSite longSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - long... longLabels) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || (!LONG_TYPES.contains(invocationType.parameterType(0)))) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(longLabels); - - assert LongStream.of(longLabels).distinct().count() == longLabels.length - : "switch labels are not distinct: " + Arrays.toString(longLabels); - - return new LongSwitchCallSite(invocationType, longLabels); - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on a {@code double} or {@code Double}. - * The static arguments are a varargs array of {@code double} labels. - * - * <p>The results are undefined if the labels array contains duplicates - * according to {@link Double#doubleToLongBits(double)}. - * - * @implNote - * - * The implementation only enforces the requirement that the labels array - * be duplicate-free if system assertions are enabled. - * - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter which is - * one of the 32-bit or shorter primitive types, or - * one of their box types, and return {@code int}. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param doubleLabels long values corresponding to the case labels of the - * {@code switch} statement. - * @return the index into {@code doubleLabels} of the target value, if the target - * matches any of the labels, {@literal -1} if the target value is - * {@code null}, or {@code doubleLabels.length} if the target value does - * not match any of the labels. - * @throws NullPointerException if any required argument is null - * @throws IllegalArgumentException if the invocation type is not - * {@code (double)int} or {@code (Double)int} - * @throws Throwable if there is any error linking the call site - */ - public static CallSite doubleSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - double... doubleLabels) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || (!DOUBLE_TYPES.contains(invocationType.parameterType(0)))) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(doubleLabels); - - long[] longLabels = new long[doubleLabels.length]; - for (int i=0; i<doubleLabels.length; i++) - longLabels[i] = Double.doubleToLongBits(doubleLabels[i]); - - assert LongStream.of(longLabels).distinct().count() == longLabels.length - : "switch labels are not distinct: " + Arrays.toString(doubleLabels); - - return new LongSwitchCallSite(invocationType, longLabels); - } - - static class LongSwitchCallSite extends ConstantCallSite { - private final long[] labels; - private final int[] indexes; - - LongSwitchCallSite(MethodType targetType, - long[] longLabels) throws Throwable { - super(targetType, CONSTANT_INIT_HOOK); - - // expensive way to index an array - indexes = IntStream.range(0, longLabels.length) - .boxed() - .sorted(Comparator.comparingLong(a -> longLabels[a])) - .mapToInt(Integer::intValue) - .toArray(); - labels = new long[indexes.length]; - for (int i=0; i<indexes.length; i++) - labels[i] = longLabels[indexes[i]]; - } - - int doSwitch(long target) { - int index = Arrays.binarySearch(labels, target); - return (index >= 0) ? indexes[index] : indexes.length; - } - - int doSwitch(double target) { - return doSwitch(Double.doubleToLongBits(target)); - } - - int doSwitch(Long target) { - return (target == null) ? -1 : doSwitch((long) target); - } - - int doSwitch(Double target) { - return (target == null) ? -1 : doSwitch((double) target); - } - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on a {@code String} target. The static - * arguments are a varargs array of {@code String} labels. - * - * <p>The results are undefined if the labels array contains duplicates - * according to {@link String#equals(Object)}. - * - * @implNote - * - * The implementation only enforces the requirement that the labels array - * be duplicate-free if system assertions are enabled. - * - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter of - * {@code String}, and return {@code int}. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param stringLabels non-null string values corresponding to the case - * labels of the {@code switch} statement. - * @return the index into {@code labels} of the target value, if the target - * matches any of the labels, {@literal -1} if the target value is - * {@code null}, or {@code stringLabels.length} if the target value - * does not match any of the labels. - * @throws NullPointerException if any required argument is null - * @throws IllegalArgumentException if any labels are null, or if the - * invocation type is not {@code (String)int} - * @throws Throwable if there is any error linking the call site - */ - public static CallSite stringSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - String... stringLabels) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || (!invocationType.parameterType(0).equals(String.class))) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(stringLabels); - if (Stream.of(stringLabels).anyMatch(Objects::isNull)) - throw new IllegalArgumentException("null label found"); - - assert Stream.of(stringLabels).distinct().count() == stringLabels.length - : "switch labels are not distinct: " + Arrays.toString(stringLabels); - - return new StringSwitchCallSite(invocationType, stringLabels); - } - - static class StringSwitchCallSite extends ConstantCallSite { - private static final Comparator<String> STRING_BY_HASH - = Comparator.comparingInt(Objects::hashCode); - - private final String[] sortedByHash; - private final int[] indexes; - private final boolean collisions; - - StringSwitchCallSite(MethodType targetType, - String[] stringLabels) throws Throwable { - super(targetType, CONSTANT_INIT_HOOK); - - // expensive way to index an array - indexes = IntStream.range(0, stringLabels.length) - .boxed() - .sorted(Comparator.comparingInt(i -> stringLabels[i].hashCode())) - .mapToInt(Integer::intValue) - .toArray(); - sortedByHash = new String[indexes.length]; - for (int i=0; i<indexes.length; i++) - sortedByHash[i] = stringLabels[indexes[i]]; - - collisions = IntStream.range(0, sortedByHash.length-1) - .anyMatch(i -> sortedByHash[i].hashCode() == sortedByHash[i + 1].hashCode()); - } - - int doSwitch(String target) { - if (target == null) - return -1; - - int index = Arrays.binarySearch(sortedByHash, target, STRING_BY_HASH); - if (index < 0) - return indexes.length; - else if (target.equals(sortedByHash[index])) { - return indexes[index]; - } - else if (collisions) { - int hash = target.hashCode(); - while (index > 0 && sortedByHash[index-1].hashCode() == hash) - --index; - for (; index < sortedByHash.length && sortedByHash[index].hashCode() == hash; index++) - if (target.equals(sortedByHash[index])) - return indexes[index]; - } - - return indexes.length; - } - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on an {@code Enum} target. The static - * arguments are the enum class, and a varargs arrays of {@code String} - * that are the names of the enum constants corresponding to the - * {@code case} labels. - * - * <p>The results are undefined if the names array contains duplicates. - * - * @implNote - * - * The implementation only enforces the requirement that the labels array - * be duplicate-free if system assertions are enabled. - * - * @param <E> the enum type - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter of - * {@code Enum}, and return {@code int}. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param enumClass the enum class - * @param enumNames names of the enum constants against which the target - * should be matched - * @return the index into {@code labels} of the target value, if the target - * matches any of the labels, {@literal -1} if the target value is - * {@code null}, or {@code stringLabels.length} if the target value - * does not match any of the labels. - * @throws IllegalArgumentException if the specified class is not an - * enum class, or any label name is null, - * or if the invocation type is not - * {@code (Enum)int} - * @throws NullPointerException if any required argument is null - * @throws Throwable if there is any error linking the call site - */ - public static<E extends Enum<E>> CallSite enumSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - Class<E> enumClass, - String... enumNames) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || (!invocationType.parameterType(0).equals(Enum.class))) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(enumClass); - requireNonNull(enumNames); - if (!enumClass.isEnum()) - throw new IllegalArgumentException("not an enum class"); - if (Stream.of(enumNames).anyMatch(Objects::isNull)) - throw new IllegalArgumentException("null label found"); - - assert Stream.of(enumNames).distinct().count() == enumNames.length - : "switch labels are not distinct: " + Arrays.toString(enumNames); - - return new EnumSwitchCallSite<>(invocationType, enumClass, enumNames); - } - - static class EnumSwitchCallSite<E extends Enum<E>> extends ConstantCallSite { - private final int[] ordinalMap; - - EnumSwitchCallSite(MethodType targetType, - Class<E> enumClass, - String... enumNames) throws Throwable { - super(targetType, CONSTANT_INIT_HOOK); - - ordinalMap = new int[enumClass.getEnumConstants().length]; - Arrays.fill(ordinalMap, enumNames.length); - - for (int i=0; i<enumNames.length; i++) { - try { - ordinalMap[E.valueOf(enumClass, enumNames[i]).ordinal()] = i; - } - catch (Exception e) { - // allow non-existent labels, but never match them - continue; - } - } - } - - @SuppressWarnings("rawtypes") - int doSwitch(Enum target) { - return (target == null) ? -1 : ordinalMap[target.ordinal()]; - } - } - - /** - * Bootstrap method for linking an {@code invokedynamic} call site that - * implements a {@code switch} on a reference-typed target. The static - * arguments are a varargs array of {@code Class} labels. - * - * @param lookup Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invocationName The invocation name, which is ignored. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invocationType The invocation type of the {@code CallSite}. This - * method type should have a single parameter of - * a reference type, and return {@code int}. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param types non-null {@link Class} values - * @return the index into {@code labels} of the target value, if the target - * is an instance of any of the types, {@literal -1} if the target - * value is {@code null}, or {@code types.length} if the target value - * is not an instance of any of the types - * @throws NullPointerException if any required argument is null - * @throws IllegalArgumentException if any labels are null, or if the - * invocation type is not {@code (T)int for some reference type {@code T}} - * @throws Throwable if there is any error linking the call site - */ - public static CallSite typeSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - Class<?>... types) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(int.class)) - || invocationType.parameterType(0).isPrimitive()) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(types); - - types = types.clone(); - if (Stream.of(types).anyMatch(Objects::isNull)) - throw new IllegalArgumentException("null label found"); - - assert Stream.of(types).distinct().count() == types.length - : "switch labels are not distinct: " + Arrays.toString(types); - - return new TypeSwitchCallSite(invocationType, types); - } - - static class TypeSwitchCallSite extends ConstantCallSite { - private final Class<?>[] types; - - TypeSwitchCallSite(MethodType targetType, - Class<?>[] types) throws Throwable { - super(targetType, TYPE_INIT_HOOK); - this.types = types; - } - - int doSwitch(Object target) { - if (target == null) - return -1; - - // Dumbest possible strategy - Class<?> targetClass = target.getClass(); - for (int i = 0; i < types.length; i++) { - Class<?> c = types[i]; - if (c.isAssignableFrom(targetClass)) - return i; - } - - return types.length; - } - } - - /** - * Result type for pattern switches - */ - public static class PatternSwitchResult { - /** - * The selected index, -1 if input was null, or length if not matched - */ - public final int index; - - /** - * The carrier - */ - public final Object carrier; - - /** - * Construct a PatternSwitchResult - * - * @param index the index - * @param carrier the carrier - */ - public PatternSwitchResult(int index, Object carrier) { - this.index = index; - this.carrier = carrier; - } - } - - /** - * Bootstrap for pattern switches - * - * @param lookup the lookup (ignored) - * @param invocationName the invocation name (ignored) - * @param invocationType the invocation type (must return PatternSwitchResult) - * @param patterns the patterns - * @return the result - * @throws Throwable if something went wrong - */ - public static CallSite patternSwitch(MethodHandles.Lookup lookup, - String invocationName, - MethodType invocationType, - PatternHandle... patterns) throws Throwable { - if (invocationType.parameterCount() != 1 - || (!invocationType.returnType().equals(PatternSwitchResult.class)) - || invocationType.parameterType(0).isPrimitive()) - throw new IllegalArgumentException("Illegal invocation type " + invocationType); - requireNonNull(patterns); - - patterns = patterns.clone(); - Class<?> targetType = invocationType.parameterType(0); - - for (int i = 0; i < patterns.length; i++) { - PatternHandle pattern = patterns[i]; - if (pattern.descriptor().returnType() != targetType) - patterns[i] = PatternHandles.adaptTarget(pattern, targetType); - } - - if (Stream.of(patterns).anyMatch(Objects::isNull)) - throw new IllegalArgumentException("null pattern found"); - - return new PatternSwitchCallSite(invocationType, patterns); - } - - static class PatternSwitchCallSite extends ConstantCallSite { - private final PatternHandle[] patterns; - - PatternSwitchCallSite(MethodType targetType, - PatternHandle[] patterns) throws Throwable { - super(targetType, PATTERN_INIT_HOOK); - this.patterns = patterns; - } - - PatternSwitchResult doSwitch(Object target) throws Throwable { - if (target == null) - return new PatternSwitchResult(-1, null); - - // Dumbest possible strategy - for (int i = 0; i < patterns.length; i++) { - PatternHandle e = patterns[i]; - Object o = e.tryMatch().invoke(target); - if (o != null) - return new PatternSwitchResult(i, o); - } - - return new PatternSwitchResult(patterns.length, null); - - } - } -} diff --git a/src/java.base/share/classes/java/net/ProxySelector.java b/src/java.base/share/classes/java/net/ProxySelector.java index 94f236a1bfa..f31ef0aaa1d 100644 --- a/src/java.base/share/classes/java/net/ProxySelector.java +++ b/src/java.base/share/classes/java/net/ProxySelector.java @@ -65,7 +65,7 @@ public abstract class ProxySelector { * * @see #setDefault(ProxySelector) */ - private static ProxySelector theProxySelector; + private static volatile ProxySelector theProxySelector; static { try { diff --git a/src/java.base/share/classes/java/security/SecureClassLoader.java b/src/java.base/share/classes/java/security/SecureClassLoader.java index 0f2983a40bd..8cb7bed527f 100644 --- a/src/java.base/share/classes/java/security/SecureClassLoader.java +++ b/src/java.base/share/classes/java/security/SecureClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,4 +269,11 @@ public boolean equals(Object obj) { return cs.matchCerts(csk.cs, true); } } + + /** + * Called by the VM, during -Xshare:dump + */ + private void resetArchivedStates() { + pdcache.clear(); + } } diff --git a/src/java.base/share/classes/java/security/spec/MGF1ParameterSpec.java b/src/java.base/share/classes/java/security/spec/MGF1ParameterSpec.java index 109328d4549..2a09965cf3e 100644 --- a/src/java.base/share/classes/java/security/spec/MGF1ParameterSpec.java +++ b/src/java.base/share/classes/java/security/spec/MGF1ParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * 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,6 +108,34 @@ public class MGF1ParameterSpec implements AlgorithmParameterSpec { public static final MGF1ParameterSpec SHA512_256 = new MGF1ParameterSpec("SHA-512/256"); + /** + * The MGF1ParameterSpec which uses SHA3-224 message digest + * @since 16 + */ + public static final MGF1ParameterSpec SHA3_224 = + new MGF1ParameterSpec("SHA3-224"); + + /** + * The MGF1ParameterSpec which uses SHA3-256 message digest + * @since 16 + */ + public static final MGF1ParameterSpec SHA3_256 = + new MGF1ParameterSpec("SHA3-256"); + + /** + * The MGF1ParameterSpec which uses SHA3-384 message digest + * @since 16 + */ + public static final MGF1ParameterSpec SHA3_384 = + new MGF1ParameterSpec("SHA3-384"); + + /** + * The MGF1ParameterSpec which uses SHA3-512 message digest + * @since 16 + */ + public static final MGF1ParameterSpec SHA3_512 = + new MGF1ParameterSpec("SHA3-512"); + private String mdName; /** diff --git a/src/java.base/share/classes/java/util/Calendar.java b/src/java.base/share/classes/java/util/Calendar.java index 0b0974843f3..5d3da1a1b50 100644 --- a/src/java.base/share/classes/java/util/Calendar.java +++ b/src/java.base/share/classes/java/util/Calendar.java @@ -1796,8 +1796,10 @@ public final Date getTime() { * @param date the given Date. * @see #getTime() * @see #setTimeInMillis(long) + * @throws NullPointerException if {@code date} is {@code null} */ public final void setTime(Date date) { + Objects.requireNonNull(date, "date must not be null"); setTimeInMillis(date.getTime()); } diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index 43c56a86bb0..17f599d47c3 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -423,7 +423,9 @@ private Manifest getManifestFromReference() throws IOException { } man = new Manifest(jv, new ByteArrayInputStream(b), getName()); } else { - man = new Manifest(super.getInputStream(manEntry), getName()); + try (InputStream is = super.getInputStream(manEntry)) { + man = new Manifest(is, getName()); + } } manRef = new SoftReference<>(man); } diff --git a/src/java.base/share/classes/java/util/stream/Stream.java b/src/java.base/share/classes/java/util/stream/Stream.java index 742fa8d488e..d00740bb830 100644 --- a/src/java.base/share/classes/java/util/stream/Stream.java +++ b/src/java.base/share/classes/java/util/stream/Stream.java @@ -375,7 +375,7 @@ public interface Stream<T> extends BaseStream<T, Stream<T>> { * </ul> * * <p>If a lambda expression is provided as the mapper function argument, additional type - * information maybe be necessary for proper inference of the element type {@code <R>} of + * information may be necessary for proper inference of the element type {@code <R>} of * the returned stream. This can be provided in the form of explicit type declarations for * the lambda parameters or as an explicit type argument to the {@code mapMulti} call. * diff --git a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java index 92beb7b8d92..db61ee2da23 100644 --- a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,9 @@ public class GZIPOutputStream extends DeflaterOutputStream { */ private static final int TRAILER_SIZE = 8; + // Represents the default "unknown" value for OS header, per RFC-1952 + private static final byte OS_UNKNOWN = (byte) 255; + /** * Creates a new output stream with the specified buffer size. * @@ -189,7 +192,7 @@ private void writeHeader() throws IOException { 0, // Modification time MTIME (int) 0, // Modification time MTIME (int) 0, // Extra flags (XFLG) - 0 // Operating system (OS) + OS_UNKNOWN // Operating system (OS) }); } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index c89275a335c..edcc5ed5caf 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -256,6 +256,12 @@ public interface JavaLangAccess { */ ServicesCatalog getServicesCatalog(ModuleLayer layer); + /** + * Record that this layer has at least one module defined to the given + * class loader. + */ + void bindToLoader(ModuleLayer layer, ClassLoader loader); + /** * Returns an ordered stream of layers. The first element is the * given layer, the remaining elements are its parents, in DFS order. diff --git a/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java b/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java new file mode 100644 index 00000000000..48cd4e2e6dc --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.loader; + +import java.util.Map; +import jdk.internal.misc.VM; +import jdk.internal.module.ServicesCatalog; + +/** + * Used to archive the built-in class loaders, their services catalogs, and the + * package-to-module map used by the built-in class loaders. + */ +class ArchivedClassLoaders { + private static ArchivedClassLoaders archivedClassLoaders; + + private final ClassLoader bootLoader; + private final ClassLoader platformLoader; + private final ClassLoader appLoader; + private final ServicesCatalog[] servicesCatalogs; + private final Map<String, ?> packageToModule; + + private ArchivedClassLoaders() { + bootLoader = ClassLoaders.bootLoader(); + platformLoader = ClassLoaders.platformClassLoader(); + appLoader = ClassLoaders.appClassLoader(); + + servicesCatalogs = new ServicesCatalog[3]; + servicesCatalogs[0] = BootLoader.getServicesCatalog(); + servicesCatalogs[1] = ServicesCatalog.getServicesCatalog(platformLoader); + servicesCatalogs[2] = ServicesCatalog.getServicesCatalog(appLoader); + + packageToModule = BuiltinClassLoader.packageToModule(); + } + + ClassLoader bootLoader() { + return bootLoader; + } + + ClassLoader platformLoader() { + return platformLoader; + } + + ClassLoader appLoader() { + return appLoader; + } + + ServicesCatalog servicesCatalog(ClassLoader loader) { + if (loader == null) { + return servicesCatalogs[0]; + } else if (loader == platformLoader) { + return servicesCatalogs[1]; + } else if (loader == appLoader) { + return servicesCatalogs[2]; + } else { + throw new InternalError(); + } + } + + Map<String, ?> packageToModule() { + return packageToModule; + } + + static void archive() { + archivedClassLoaders = new ArchivedClassLoaders(); + } + + static ArchivedClassLoaders get() { + return archivedClassLoaders; + } + + static { + VM.initializeFromArchive(ArchivedClassLoaders.class); + } +} diff --git a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java index 2a8d7c4e7b4..671917edad3 100644 --- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java +++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java @@ -65,7 +65,15 @@ private BootLoader() { } } // ServiceCatalog for the boot class loader - private static final ServicesCatalog SERVICES_CATALOG = ServicesCatalog.create(); + private static final ServicesCatalog SERVICES_CATALOG; + static { + ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get(); + if (archivedClassLoaders != null) { + SERVICES_CATALOG = archivedClassLoaders.servicesCatalog(null); + } else { + SERVICES_CATALOG = ServicesCatalog.create(); + } + } // ClassLoaderValue map for the boot class loader private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP diff --git a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java index 21d44413060..39fe750c1e4 100644 --- a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java +++ b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java @@ -104,8 +104,7 @@ public class BuiltinClassLoader private final BuiltinClassLoader parent; // the URL class path, or null if there is no class path - private final URLClassPath ucp; - + private @Stable URLClassPath ucp; /** * A module defined/loaded by a built-in class loader. @@ -156,10 +155,26 @@ private URL createURL(URI uri) { } } - // maps package name to loaded module for modules in the boot layer - private static final Map<String, LoadedModule> packageToModule - = new ConcurrentHashMap<>(1024); + private static final Map<String, LoadedModule> packageToModule; + static { + ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get(); + if (archivedClassLoaders != null) { + @SuppressWarnings("unchecked") + Map<String, LoadedModule> map + = (Map<String, LoadedModule>) archivedClassLoaders.packageToModule(); + packageToModule = map; + } else { + packageToModule = new ConcurrentHashMap<>(1024); + } + } + + /** + * Invoked by ArchivedClassLoaders to archive the package-to-module map. + */ + static Map<String, ?> packageToModule() { + return packageToModule; + } // maps a module name to a module reference private final Map<String, ModuleReference> nameToModule; @@ -185,6 +200,21 @@ private URL createURL(URI uri) { this.moduleToReader = new ConcurrentHashMap<>(); } + /** + * Appends to the given file path to the class path. + */ + void appendClassPath(String path) { + // assert ucp != null; + ucp.addFile(path); + } + + /** + * Sets the class path, called to reset the class path during -Xshare:dump + */ + void setClassPath(URLClassPath ucp) { + this.ucp = ucp; + } + /** * Returns {@code true} if there is a class path associated with this * class loader. @@ -1042,4 +1072,9 @@ private boolean isOpen(ModuleReference mref, String pn) { private static URL checkURL(URL url) { return URLClassPath.checkURL(url); } + + // Called from VM only, during -Xshare:dump + private void resetArchivedStates() { + ucp = null; + } } diff --git a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java index f87d24f8dd5..ea9307aa148 100644 --- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java +++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java @@ -36,6 +36,7 @@ import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.VM; +import jdk.internal.module.ServicesCatalog; /** * Creates and provides access to the built-in platform and application class @@ -56,14 +57,22 @@ private ClassLoaders() { } // Creates the built-in class loaders. static { - // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute - String append = VM.getSavedProperty("jdk.boot.class.path.append"); - BOOT_LOADER = - new BootClassLoader((append != null && !append.isEmpty()) - ? new URLClassPath(append, true) - : null); - PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER); - + ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get(); + if (archivedClassLoaders != null) { + // assert VM.getSavedProperty("jdk.boot.class.path.append") == null + BOOT_LOADER = (BootClassLoader) archivedClassLoaders.bootLoader(); + PLATFORM_LOADER = (PlatformClassLoader) archivedClassLoaders.platformLoader(); + ServicesCatalog catalog = archivedClassLoaders.servicesCatalog(PLATFORM_LOADER); + ServicesCatalog.putServicesCatalog(PLATFORM_LOADER, catalog); + } else { + // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute + String append = VM.getSavedProperty("jdk.boot.class.path.append"); + URLClassPath ucp = (append != null && !append.isEmpty()) + ? new URLClassPath(append, true) + : null; + BOOT_LOADER = new BootClassLoader(ucp); + PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER); + } // A class path is required when no initial module is specified. // In this case the class path defaults to "", meaning the current // working directory. When an initial module is specified, on the @@ -75,7 +84,15 @@ private ClassLoaders() { } cp = (initialModuleName == null) ? "" : null; } URLClassPath ucp = new URLClassPath(cp, false); - APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp); + if (archivedClassLoaders != null) { + APP_LOADER = (AppClassLoader) archivedClassLoaders.appLoader(); + ServicesCatalog catalog = archivedClassLoaders.servicesCatalog(APP_LOADER); + ServicesCatalog.putServicesCatalog(APP_LOADER, catalog); + APP_LOADER.setClassPath(ucp); + } else { + APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp); + ArchivedClassLoaders.archive(); + } } /** @@ -144,11 +161,8 @@ private static class AppClassLoader extends BuiltinClassLoader { throw new InternalError(); } - final URLClassPath ucp; - - AppClassLoader(PlatformClassLoader parent, URLClassPath ucp) { + AppClassLoader(BuiltinClassLoader parent, URLClassPath ucp) { super("app", parent, ucp); - this.ucp = ucp; } @Override @@ -181,7 +195,7 @@ protected PermissionCollection getPermissions(CodeSource cs) { * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch */ void appendToClassPathForInstrumentation(String path) { - ucp.addFile(path); + appendClassPath(path); } /** @@ -190,6 +204,13 @@ void appendToClassPathForInstrumentation(String path) { protected Package defineOrCheckPackage(String pn, Manifest man, URL url) { return super.defineOrCheckPackage(pn, man, url); } + + /** + * Called by the VM, during -Xshare:dump + */ + private void resetArchivedStates() { + setClassPath(null); + } } /** diff --git a/src/java.base/share/classes/jdk/internal/misc/VM.java b/src/java.base/share/classes/jdk/internal/misc/VM.java index ed753a58ca2..5681a79558f 100644 --- a/src/java.base/share/classes/jdk/internal/misc/VM.java +++ b/src/java.base/share/classes/jdk/internal/misc/VM.java @@ -468,6 +468,8 @@ public static boolean isSetUID() { */ public static native void initializeFromArchive(Class<?> c); + public static native void defineArchivedModules(ClassLoader platformLoader, ClassLoader systemLoader); + public static native long getRandomSeedForCDSDump(); /** diff --git a/src/java.base/share/classes/jdk/internal/module/ArchivedBootLayer.java b/src/java.base/share/classes/jdk/internal/module/ArchivedBootLayer.java new file mode 100644 index 00000000000..90bd5eaa51e --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/module/ArchivedBootLayer.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.module; + +import jdk.internal.misc.VM; + +/** + * Used by ModuleBootstrap for archiving the boot layer and the builder needed to + * set the IllegalAccessLogger. + */ +class ArchivedBootLayer { + private static ArchivedBootLayer archivedBootLayer; + + private final ModuleLayer bootLayer; + private final IllegalAccessLogger.Builder builder; + + private ArchivedBootLayer(ModuleLayer bootLayer, + IllegalAccessLogger.Builder builder) { + this.bootLayer = bootLayer; + this.builder = builder; + } + + ModuleLayer bootLayer() { + return bootLayer; + } + + IllegalAccessLogger.Builder illegalAccessLoggerBuilder() { + return builder; + } + + static ArchivedBootLayer get() { + return archivedBootLayer; + } + + static void archive(ModuleLayer layer, IllegalAccessLogger.Builder builder) { + archivedBootLayer = new ArchivedBootLayer(layer, builder); + } + + static { + VM.initializeFromArchive(ArchivedBootLayer.class); + } +} diff --git a/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java b/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java index 348d943106a..6b038238eb1 100644 --- a/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java +++ b/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java @@ -22,21 +22,20 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.internal.module; -import java.lang.module.Configuration; -import java.lang.module.ModuleFinder; import java.util.Map; import java.util.Set; import java.util.function.Function; - +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; import jdk.internal.misc.VM; /** - * Used by ModuleBootstrap to obtain the archived system modules and finder. + * Used by ModuleBootstrap for archiving the configuration for the boot layer, + * the system module finder, and the maps used to create the IllegalAccessLogger. */ -final class ArchivedModuleGraph { +class ArchivedModuleGraph { private static ArchivedModuleGraph archivedModuleGraph; private final boolean hasSplitPackages; @@ -47,13 +46,13 @@ final class ArchivedModuleGraph { private final Map<String, Set<String>> concealedPackagesToOpen; private final Map<String, Set<String>> exportedPackagesToOpen; - public ArchivedModuleGraph(boolean hasSplitPackages, - boolean hasIncubatorModules, - ModuleFinder finder, - Configuration configuration, - Function<String, ClassLoader> classLoaderFunction, - Map<String, Set<String>> concealedPackagesToOpen, - Map<String, Set<String>> exportedPackagesToOpen) { + private ArchivedModuleGraph(boolean hasSplitPackages, + boolean hasIncubatorModules, + ModuleFinder finder, + Configuration configuration, + Function<String, ClassLoader> classLoaderFunction, + Map<String, Set<String>> concealedPackagesToOpen, + Map<String, Set<String>> exportedPackagesToOpen) { this.hasSplitPackages = hasSplitPackages; this.hasIncubatorModules = hasIncubatorModules; this.finder = finder; @@ -107,8 +106,20 @@ static ArchivedModuleGraph get(String mainModule) { /** * Archive the module graph for the given initial module. */ - static void archive(ArchivedModuleGraph graph) { - archivedModuleGraph = graph; + static void archive(boolean hasSplitPackages, + boolean hasIncubatorModules, + ModuleFinder finder, + Configuration configuration, + Function<String, ClassLoader> classLoaderFunction, + Map<String, Set<String>> concealedPackagesToOpen, + Map<String, Set<String>> exportedPackagesToOpen) { + archivedModuleGraph = new ArchivedModuleGraph(hasSplitPackages, + hasIncubatorModules, + finder, + configuration, + classLoaderFunction, + concealedPackagesToOpen, + exportedPackagesToOpen); } static { diff --git a/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java b/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java index 1368c17d8cd..2a67401d18b 100644 --- a/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java +++ b/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ public final class IllegalAccessLogger { /** * Logger modes */ - public static enum Mode { + public enum Mode { /** * Prints a warning when an illegal access succeeds and then * discards the logger so that there is no further output. @@ -118,7 +118,7 @@ public Builder logAccessToExportedPackages(Module m, Set<String> packages) { } /** - * Builds the IllegalAccessLogger and sets it as the system-wise logger. + * Builds the IllegalAccessLogger and sets it as the system-wide logger. */ public void complete() { Map<Module, Set<String>> map1 = unmodifiableMap(moduleToConcealedPackages); diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index ed6fb613310..bc872c44917 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -42,18 +42,19 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -import jdk.internal.loader.BootLoader; -import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.JavaLangModuleAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.loader.BootLoader; +import jdk.internal.loader.BuiltinClassLoader; +import jdk.internal.loader.ClassLoaders; +import jdk.internal.misc.VM; import jdk.internal.perf.PerfCounter; /** @@ -86,8 +87,8 @@ private ModuleBootstrap() { } private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; // access to java.lang/module - private static final JavaLangModuleAccess JLMA - = SharedSecrets.getJavaLangModuleAccess(); + private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); // The ModulePatcher for the initial configuration private static final ModulePatcher patcher = initModulePatcher(); @@ -134,14 +135,58 @@ public static ModuleFinder limitedFinder() { } /** - * Initialize the module system, returning the boot layer. + * Returns true if the archived boot layer can be used. The system properties + * are checked in the order that they are used by boot2. + */ + private static boolean canUseArchivedBootLayer() { + return getProperty("jdk.module.upgrade.path") == null && + getProperty("jdk.module.path") == null && + getProperty("jdk.module.patch.0") == null && // --patch-module + getProperty("jdk.module.main") == null && + getProperty("jdk.module.addmods.0") == null && // --add-modules + getProperty("jdk.module.limitmods") == null && + getProperty("jdk.module.addreads.0") == null && // --add-reads + getProperty("jdk.module.addexports.0") == null && // --add-exports + getProperty("jdk.module.addopens.0") == null && // --add-opens + getProperty("jdk.module.illegalAccess") == null; + } + + /** + * Initialize the module system, returning the boot layer. The boot layer + * is obtained from the CDS archive if possible, otherwise it is generated + * from the module graph. * * @see java.lang.System#initPhase2(boolean, boolean) */ - public static ModuleLayer boot() throws Exception { - + public static ModuleLayer boot() { Counters.start(); + ModuleLayer bootLayer; + ArchivedBootLayer archivedBootLayer = ArchivedBootLayer.get(); + if (archivedBootLayer != null) { + assert canUseArchivedBootLayer(); + bootLayer = archivedBootLayer.bootLayer(); + BootLoader.getUnnamedModule(); // trigger <clinit> of BootLoader. + VM.defineArchivedModules(ClassLoaders.platformClassLoader(), ClassLoaders.appClassLoader()); + + // assume boot layer has at least one module providing a service + // that is mapped to the application class loader. + JLA.bindToLoader(bootLayer, ClassLoaders.appClassLoader()); + + // IllegalAccessLogger needs to be set + var illegalAccessLoggerBuilder = archivedBootLayer.illegalAccessLoggerBuilder(); + if (illegalAccessLoggerBuilder != null) { + illegalAccessLoggerBuilder.complete(); + } + } else { + bootLayer = boot2(); + } + + Counters.publish("jdk.module.boot.totalTime"); + return bootLayer; + } + + private static ModuleLayer boot2() { // Step 0: Command line options ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path"); @@ -428,11 +473,12 @@ public static ModuleLayer boot() throws Exception { concealedPackagesToOpen = systemModules.concealedPackagesToOpen(); exportedPackagesToOpen = systemModules.exportedPackagesToOpen(); } - addIllegalAccess(upgradeModulePath, - concealedPackagesToOpen, - exportedPackagesToOpen, - bootLayer, - extraExportsOrOpens); + IllegalAccessLogger.Builder builder = + addIllegalAccess(upgradeModulePath, + concealedPackagesToOpen, + exportedPackagesToOpen, + bootLayer, + extraExportsOrOpens); Counters.add("jdk.module.boot.7.adjustModulesTime"); // save module finders for later use @@ -442,22 +488,22 @@ public static ModuleLayer boot() throws Exception { limitedFinder = new SafeModuleFinder(finder); } - // Module graph can be archived at CDS dump time. Only allow the - // unnamed module case for now. + // Archive module graph and boot layer can be archived at CDS dump time. + // Only allow the unnamed module case for now. if (canArchive && (mainModule == null)) { - ArchivedModuleGraph.archive( - new ArchivedModuleGraph(hasSplitPackages, - hasIncubatorModules, - systemModuleFinder, - cf, - clf, - concealedPackagesToOpen, - exportedPackagesToOpen)); + ArchivedModuleGraph.archive(hasSplitPackages, + hasIncubatorModules, + systemModuleFinder, + cf, + clf, + concealedPackagesToOpen, + exportedPackagesToOpen); + + if (!hasSplitPackages && !hasIncubatorModules) { + ArchivedBootLayer.archive(bootLayer, builder); + } } - // total time to initialize - Counters.publish("jdk.module.boot.totalTime"); - return bootLayer; } @@ -751,17 +797,18 @@ private static void addExtraExportsOrOpens(ModuleLayer bootLayer, * Process the --illegal-access option (and its default) to open packages * of system modules in the boot layer to code in unnamed modules. */ - private static void addIllegalAccess(ModuleFinder upgradeModulePath, - Map<String, Set<String>> concealedPackagesToOpen, - Map<String, Set<String>> exportedPackagesToOpen, - ModuleLayer bootLayer, - boolean extraExportsOrOpens) { + private static IllegalAccessLogger.Builder + addIllegalAccess(ModuleFinder upgradeModulePath, + Map<String, Set<String>> concealedPackagesToOpen, + Map<String, Set<String>> exportedPackagesToOpen, + ModuleLayer bootLayer, + boolean extraExportsOrOpens) { String value = getAndRemoveProperty("jdk.module.illegalAccess"); IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT; if (value != null) { switch (value) { case "deny": - return; + return null; case "permit": break; case "warn": @@ -773,7 +820,7 @@ private static void addIllegalAccess(ModuleFinder upgradeModulePath, default: fail("Value specified to --illegal-access not recognized:" + " '" + value + "'"); - return; + return null; } } IllegalAccessLogger.Builder builder @@ -836,11 +883,11 @@ private static void addIllegalAccess(ModuleFinder upgradeModulePath, builder.logAccessToExportedPackages(m, exportedPackages); // open the packages to unnamed modules - JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); - jla.addOpensToAllUnnamed(m, concealedPackages, exportedPackages); + JLA.addOpensToAllUnnamed(m, concealedPackages, exportedPackages); } builder.complete(); + return builder; } /** @@ -905,11 +952,19 @@ private static Map<String, List<String>> decode(String prefix) { return decode(prefix, ",", true); } + + /** + * Gets the named system property + */ + private static String getProperty(String key) { + return System.getProperty(key); + } + /** * Gets and remove the named system property */ private static String getAndRemoveProperty(String key) { - return (String)System.getProperties().remove(key); + return (String) System.getProperties().remove(key); } /** diff --git a/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java b/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java index 811fbccb852..3590cf7c430 100644 --- a/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java +++ b/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java @@ -171,6 +171,16 @@ public static ServicesCatalog getServicesCatalog(ClassLoader loader) { return catalog; } + /** + * Associates the given ServicesCatalog with the given class loader. + */ + public static void putServicesCatalog(ClassLoader loader, ServicesCatalog catalog) { + ServicesCatalog previous = CLV.putIfAbsent(loader, catalog); + if (previous != null) { + throw new InternalError(); + } + } + // the ServicesCatalog registered to a class loader private static final ClassLoaderValue<ServicesCatalog> CLV = new ClassLoaderValue<>(); } diff --git a/src/java.base/share/classes/sun/net/www/ParseUtil.java b/src/java.base/share/classes/sun/net/www/ParseUtil.java index f8963225348..c73c52e15d8 100644 --- a/src/java.base/share/classes/sun/net/www/ParseUtil.java +++ b/src/java.base/share/classes/sun/net/www/ParseUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * 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,10 +34,10 @@ import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; -import sun.nio.cs.ThreadLocalCoders; import sun.nio.cs.UTF_8; /** @@ -177,9 +177,9 @@ public static String decode(String s) { StringBuilder sb = new StringBuilder(n); ByteBuffer bb = ByteBuffer.allocate(n); CharBuffer cb = CharBuffer.allocate(n); - CharsetDecoder dec = ThreadLocalCoders.decoderFor(UTF_8.INSTANCE) - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT); + CharsetDecoder dec = UTF_8.INSTANCE.newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT); char c = s.charAt(0); for (int i = 0; i < n;) { @@ -451,6 +451,7 @@ private static void appendFragment(StringBuilder sb, String fragment) { private static String quote(String s, long lowMask, long highMask) { int n = s.length(); StringBuilder sb = null; + CharsetEncoder encoder = null; boolean allowNonASCII = ((lowMask & L_ESCAPED) != 0); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); @@ -468,11 +469,14 @@ private static String quote(String s, long lowMask, long highMask) { } else if (allowNonASCII && (Character.isSpaceChar(c) || Character.isISOControl(c))) { + if (encoder == null) { + encoder = UTF_8.INSTANCE.newEncoder(); + } if (sb == null) { sb = new StringBuilder(); sb.append(s, 0, i); } - appendEncoded(sb, c); + appendEncoded(encoder, sb, c); } else { if (sb != null) sb.append(c); @@ -494,11 +498,11 @@ && match(s.charAt(pos + 1), L_HEX, H_HEX) && match(s.charAt(pos + 2), L_HEX, H_HEX); } - private static void appendEncoded(StringBuilder sb, char c) { + private static void appendEncoded(CharsetEncoder encoder, + StringBuilder sb, char c) { ByteBuffer bb = null; try { - bb = ThreadLocalCoders.encoderFor(UTF_8.INSTANCE) - .encode(CharBuffer.wrap("" + c)); + bb = encoder.encode(CharBuffer.wrap("" + c)); } catch (CharacterCodingException x) { assert false; } diff --git a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java index 860d5ff12c9..5c7356fca81 100644 --- a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java +++ b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java @@ -301,11 +301,12 @@ private static <D extends GenericDeclaration> AnnotatedType[] parseAnnotatedBoun l.add(t); } } + TypeAnnotation[] typeAnnotations = l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY); res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i], AnnotatedTypeFactory.nestingForType(bounds[i], loc), - l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), - candidates.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), - (AnnotatedElement)decl); + typeAnnotations, + typeAnnotations, + decl); } return res; } diff --git a/src/java.base/share/classes/sun/security/provider/DSA.java b/src/java.base/share/classes/sun/security/provider/DSA.java index b0d06c55727..a7c42a1f35a 100644 --- a/src/java.base/share/classes/sun/security/provider/DSA.java +++ b/src/java.base/share/classes/sun/security/provider/DSA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,11 +47,16 @@ * Standards and Technology (NIST), using SHA digest algorithms * from FIPS180-3. * - * This file contains both the signature implementation for the - * commonly used SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA, - * as well as RawDSA, used by TLS among others. RawDSA expects - * the 20 byte SHA-1 digest as input via update rather than the - * original data like other signature implementations. + * This file contains the signature implementation for the + * SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA, SHA384withDSA, + * SHA512withDSA, SHA3-224withDSA, SHA3-256withDSA, SHA3-384withDSA, + * SHA3-512withDSA, as well as RawDSA, used by TLS among others. + * RawDSA expects the 20 byte SHA-1 digest as input via update rather + * than the original data like other signature implementations. + * + * In addition, IEEE P1363 signature format is supported. The + * corresponding implementation is registered under <sig>inP1363Format, + * e.g. SHA256withDSAinP1363Format. * * @author Benjamin Renaud * @@ -504,6 +509,78 @@ public String toString() { return printable; } + /** + * SHA3-224withDSA implementation. + */ + public static final class SHA3_224withDSA extends DSA { + public SHA3_224withDSA() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-224")); + } + } + + /** + * SHA3-224withDSA implementation that uses the IEEE P1363 format. + */ + public static final class SHA3_224withDSAinP1363Format extends DSA { + public SHA3_224withDSAinP1363Format() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-224"), true); + } + } + + /** + * Standard SHA3-256withDSA implementation. + */ + public static final class SHA3_256withDSA extends DSA { + public SHA3_256withDSA() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-256")); + } + } + + /** + * Standard SHA3-256withDSA implementation that uses the IEEE P1363 format. + */ + public static final class SHA3_256withDSAinP1363Format extends DSA { + public SHA3_256withDSAinP1363Format() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-256"), true); + } + } + + /** + * Standard SHA3-384withDSA implementation. + */ + public static final class SHA3_384withDSA extends DSA { + public SHA3_384withDSA() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-384")); + } + } + + /** + * Standard SHA3-384withDSA implementation that uses the IEEE P1363 format. + */ + public static final class SHA3_384withDSAinP1363Format extends DSA { + public SHA3_384withDSAinP1363Format() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-384"), true); + } + } + + /** + * Standard SHA3-512withDSA implementation. + */ + public static final class SHA3_512withDSA extends DSA { + public SHA3_512withDSA() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-512")); + } + } + + /** + * Standard SHA3-512withDSA implementation that uses the IEEE P1363 format. + */ + public static final class SHA3_512withDSAinP1363Format extends DSA { + public SHA3_512withDSAinP1363Format() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA3-512"), true); + } + } + /** * Standard SHA224withDSA implementation as defined in FIPS186-3. */ @@ -540,6 +617,42 @@ public SHA256withDSAinP1363Format() throws NoSuchAlgorithmException { } } + /** + * Standard SHA384withDSA implementation as defined in FIPS186-3. + */ + public static final class SHA384withDSA extends DSA { + public SHA384withDSA() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA-384")); + } + } + + /** + * SHA384withDSA implementation that uses the IEEE P1363 format. + */ + public static final class SHA384withDSAinP1363Format extends DSA { + public SHA384withDSAinP1363Format() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA-384"), true); + } + } + + /** + * Standard SHA512withDSA implementation as defined in FIPS186-3. + */ + public static final class SHA512withDSA extends DSA { + public SHA512withDSA() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA-512")); + } + } + + /** + * SHA512withDSA implementation that uses the IEEE P1363 format. + */ + public static final class SHA512withDSAinP1363Format extends DSA { + public SHA512withDSAinP1363Format() throws NoSuchAlgorithmException { + super(MessageDigest.getInstance("SHA-512"), true); + } + } + /** * Standard SHA1withDSA implementation. */ diff --git a/src/java.base/share/classes/sun/security/provider/SunEntries.java b/src/java.base/share/classes/sun/security/provider/SunEntries.java index 79007f4d8ef..076c6e04f4f 100644 --- a/src/java.base/share/classes/sun/security/provider/SunEntries.java +++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java @@ -54,9 +54,13 @@ * SHA-2 family of hash functions includes SHA-224, SHA-256, SHA-384, * and SHA-512. * - * - SHA-224withDSA/SHA-256withDSA are the signature schemes + * - [SHA-224|SHA-256|SHA-384|SHA-512]withDSA are the signature schemes * described in FIPS 186-3. The associated object identifiers are - * "OID.2.16.840.1.101.3.4.3.1", and "OID.2.16.840.1.101.3.4.3.2". + * "OID.2.16.840.1.101.3.4.3.[1|2|3|4]" respectively. + * + * - [SHA3-224|SHA3-256|SHA3-384|SHA3-512]withDSA are the signature schemes + * using SHA-3 family of digests with DSA. The associated object identifiers + * are "OID.2.16.840.1.101.3.4.3.[5|6|7|8]" respectively. * * - DSA is the key generation scheme as described in FIPS 186. * Aliases for DSA include the OID strings "OID.1.3.14.3.2.12" @@ -127,13 +131,30 @@ public final class SunEntries { addWithAlias(p, "Signature", "NONEwithDSA", "sun.security.provider.DSA$RawDSA", attrs); - attrs.put("KeySize", "2048"); // for SHA224 and SHA256 DSA signatures + // for DSA signatures with 224/256-bit digests + attrs.put("KeySize", "2048"); addWithAlias(p, "Signature", "SHA224withDSA", "sun.security.provider.DSA$SHA224withDSA", attrs); addWithAlias(p, "Signature", "SHA256withDSA", "sun.security.provider.DSA$SHA256withDSA", attrs); + addWithAlias(p, "Signature", "SHA3-224withDSA", + "sun.security.provider.DSA$SHA3_224withDSA", attrs); + addWithAlias(p, "Signature", "SHA3-256withDSA", + "sun.security.provider.DSA$SHA3_256withDSA", attrs); + + attrs.put("KeySize", "3072"); // for DSA sig using 384/512-bit digests + + addWithAlias(p, "Signature", "SHA384withDSA", + "sun.security.provider.DSA$SHA384withDSA", attrs); + addWithAlias(p, "Signature", "SHA512withDSA", + "sun.security.provider.DSA$SHA512withDSA", attrs); + addWithAlias(p, "Signature", "SHA3-384withDSA", + "sun.security.provider.DSA$SHA3_384withDSA", attrs); + addWithAlias(p, "Signature", "SHA3-512withDSA", + "sun.security.provider.DSA$SHA3_512withDSA", attrs); + attrs.remove("KeySize"); add(p, "Signature", "SHA1withDSAinP1363Format", @@ -144,7 +165,18 @@ public final class SunEntries { "sun.security.provider.DSA$SHA224withDSAinP1363Format"); add(p, "Signature", "SHA256withDSAinP1363Format", "sun.security.provider.DSA$SHA256withDSAinP1363Format"); - + add(p, "Signature", "SHA384withDSAinP1363Format", + "sun.security.provider.DSA$SHA384withDSAinP1363Format"); + add(p, "Signature", "SHA512withDSAinP1363Format", + "sun.security.provider.DSA$SHA512withDSAinP1363Format"); + add(p, "Signature", "SHA3-224withDSAinP1363Format", + "sun.security.provider.DSA$SHA3_224withDSAinP1363Format"); + add(p, "Signature", "SHA3-256withDSAinP1363Format", + "sun.security.provider.DSA$SHA3_256withDSAinP1363Format"); + add(p, "Signature", "SHA3-384withDSAinP1363Format", + "sun.security.provider.DSA$SHA3_384withDSAinP1363Format"); + add(p, "Signature", "SHA3-512withDSAinP1363Format", + "sun.security.provider.DSA$SHA3_512withDSAinP1363Format"); /* * Key Pair Generator engines */ diff --git a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java index a4bdd4b5dca..fef496ed50c 100644 --- a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java +++ b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,7 +103,7 @@ protected void engineInit(byte[] encoded) throws IOException { throw new IOException("Only MGF1 mgf is supported"); } AlgorithmId params = AlgorithmId.parse( - new DerValue(val.getEncodedParams())); + new DerValue(val.getEncodedParams())); String mgfDigestName = params.getName(); switch (mgfDigestName) { case "SHA-1": @@ -127,6 +127,18 @@ protected void engineInit(byte[] encoded) throws IOException { case "SHA-512/256": mgfSpec = MGF1ParameterSpec.SHA512_256; break; + case "SHA3-224": + mgfSpec = MGF1ParameterSpec.SHA3_224; + break; + case "SHA3-256": + mgfSpec = MGF1ParameterSpec.SHA3_256; + break; + case "SHA3-384": + mgfSpec = MGF1ParameterSpec.SHA3_384; + break; + case "SHA3-512": + mgfSpec = MGF1ParameterSpec.SHA3_512; + break; default: throw new IOException ("Unrecognized message digest algorithm " + diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java index e95408b9f62..85eb219a7d9 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java @@ -45,8 +45,8 @@ * PKCS#1 v2.2 RSASSA-PSS signatures with various message digest algorithms. * RSASSA-PSS implementation takes the message digest algorithm, MGF algorithm, * and salt length values through the required signature PSS parameters. - * We support SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and - * SHA-512/256 message digest algorithms and MGF1 mask generation function. + * We support SHA-1, SHA-2 family and SHA3 family of message digest algorithms, + * and MGF1 mask generation function. * * @since 11 */ @@ -81,24 +81,20 @@ private boolean isDigestEqual(String stdAlg, String givenAlg) { private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8]; - private static final Hashtable<String, Integer> DIGEST_LENGTHS = - new Hashtable<String, Integer>(); + private static final Hashtable<KnownOIDs, Integer> DIGEST_LENGTHS = + new Hashtable<KnownOIDs, Integer>(); static { - DIGEST_LENGTHS.put("SHA-1", 20); - DIGEST_LENGTHS.put("SHA", 20); - DIGEST_LENGTHS.put("SHA1", 20); - DIGEST_LENGTHS.put("SHA-224", 28); - DIGEST_LENGTHS.put("SHA224", 28); - DIGEST_LENGTHS.put("SHA-256", 32); - DIGEST_LENGTHS.put("SHA256", 32); - DIGEST_LENGTHS.put("SHA-384", 48); - DIGEST_LENGTHS.put("SHA384", 48); - DIGEST_LENGTHS.put("SHA-512", 64); - DIGEST_LENGTHS.put("SHA512", 64); - DIGEST_LENGTHS.put("SHA-512/224", 28); - DIGEST_LENGTHS.put("SHA512/224", 28); - DIGEST_LENGTHS.put("SHA-512/256", 32); - DIGEST_LENGTHS.put("SHA512/256", 32); + DIGEST_LENGTHS.put(KnownOIDs.SHA_1, 20); + DIGEST_LENGTHS.put(KnownOIDs.SHA_224, 28); + DIGEST_LENGTHS.put(KnownOIDs.SHA_256, 32); + DIGEST_LENGTHS.put(KnownOIDs.SHA_384, 48); + DIGEST_LENGTHS.put(KnownOIDs.SHA_512, 64); + DIGEST_LENGTHS.put(KnownOIDs.SHA_512$224, 28); + DIGEST_LENGTHS.put(KnownOIDs.SHA_512$256, 32); + DIGEST_LENGTHS.put(KnownOIDs.SHA3_224, 28); + DIGEST_LENGTHS.put(KnownOIDs.SHA3_256, 32); + DIGEST_LENGTHS.put(KnownOIDs.SHA3_384, 48); + DIGEST_LENGTHS.put(KnownOIDs.SHA3_512, 64); } // message digest implementation we use for hashing the data @@ -210,27 +206,33 @@ private static boolean isCompatible(AlgorithmParameterSpec keyParams, * internal signature parameters. */ private RSAKey isValid(RSAKey rsaKey) throws InvalidKeyException { - try { - AlgorithmParameterSpec keyParams = rsaKey.getParams(); - // validate key parameters - if (!isCompatible(rsaKey.getParams(), this.sigParams)) { - throw new InvalidKeyException - ("Key contains incompatible PSS parameter values"); - } - // validate key length - if (this.sigParams != null) { - Integer hLen = - DIGEST_LENGTHS.get(this.sigParams.getDigestAlgorithm()); - if (hLen == null) { - throw new ProviderException("Unsupported digest algo: " + - this.sigParams.getDigestAlgorithm()); + AlgorithmParameterSpec keyParams = rsaKey.getParams(); + // validate key parameters + if (!isCompatible(rsaKey.getParams(), this.sigParams)) { + throw new InvalidKeyException + ("Key contains incompatible PSS parameter values"); + } + // validate key length + if (this.sigParams != null) { + String digestAlgo = this.sigParams.getDigestAlgorithm(); + KnownOIDs ko = KnownOIDs.findMatch(digestAlgo); + if (ko != null) { + Integer hLen = DIGEST_LENGTHS.get(ko); + if (hLen != null) { + checkKeyLength(rsaKey, hLen, + this.sigParams.getSaltLength()); + } else { + // should never happen; checked in validateSigParams() + throw new ProviderException + ("Unsupported digest algo: " + digestAlgo); } - checkKeyLength(rsaKey, hLen, this.sigParams.getSaltLength()); + } else { + // should never happen; checked in validateSigParams() + throw new ProviderException + ("Unrecognized digest algo: " + digestAlgo); } - return rsaKey; - } catch (SignatureException e) { - throw new InvalidKeyException(e); } + return rsaKey; } /** @@ -268,14 +270,26 @@ private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p) ("Only supports TrailerFieldBC(1)"); } - String digestAlgo = params.getDigestAlgorithm(); + // check key length again if (key != null) { - try { - int hLen = DIGEST_LENGTHS.get(digestAlgo); - checkKeyLength(key, hLen, params.getSaltLength()); - } catch (SignatureException e) { - throw new InvalidAlgorithmParameterException(e); + String digestAlgo = params.getDigestAlgorithm(); + KnownOIDs ko = KnownOIDs.findMatch(digestAlgo); + if (ko != null) { + Integer hLen = DIGEST_LENGTHS.get(ko); + if (hLen != null) { + try { + checkKeyLength(key, hLen, params.getSaltLength()); + } catch (InvalidKeyException e) { + throw new InvalidAlgorithmParameterException(e); + } + } else { + throw new InvalidAlgorithmParameterException + ("Unsupported digest algo: " + digestAlgo); + } + } else { + throw new InvalidAlgorithmParameterException + ("Unrecognized digest algo: " + digestAlgo); } } return params; @@ -302,12 +316,12 @@ private void ensureInit() throws SignatureException { * salt length */ private static void checkKeyLength(RSAKey key, int digestLen, - int saltLen) throws SignatureException { + int saltLen) throws InvalidKeyException { if (key != null) { int keyLength = (getKeyLengthInBits(key) + 7) >> 3; int minLength = Math.addExact(Math.addExact(digestLen, saltLen), 2); if (keyLength < minLength) { - throw new SignatureException + throw new InvalidKeyException ("Key is too short, need min " + minLength + " bytes"); } } diff --git a/src/java.base/share/classes/sun/security/rsa/RSASignature.java b/src/java.base/share/classes/sun/security/rsa/RSASignature.java index ea2ef985082..795d5c59020 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSASignature.java +++ b/src/java.base/share/classes/sun/security/rsa/RSASignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,8 +40,9 @@ * PKCS#1 v1.5 RSA signatures with the various message digest algorithms. * This file contains an abstract base class with all the logic plus * a nested static class for each of the message digest algorithms - * (see end of the file). We support MD2, MD5, SHA-1, SHA-224, SHA-256, - * SHA-384, SHA-512, SHA-512/224, and SHA-512/256. + * (see end of the file). We support MD2, MD5, SHA-1, SHA2 family ( + * SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256), + * and SHA3 family (SHA3-224, SHA3-256, SHA3-384, SHA3-512) of digests. * * @since 1.5 * @author Andreas Sterbenz @@ -360,4 +361,32 @@ public SHA512_256withRSA() { super("SHA-512/256", AlgorithmId.SHA512_256_oid, 11); } } + + // Nested class for SHA3-224withRSA signatures + public static final class SHA3_224withRSA extends RSASignature { + public SHA3_224withRSA() { + super("SHA3-224", AlgorithmId.SHA3_224_oid, 11); + } + } + + // Nested class for SHA3-256withRSA signatures + public static final class SHA3_256withRSA extends RSASignature { + public SHA3_256withRSA() { + super("SHA3-256", AlgorithmId.SHA3_256_oid, 11); + } + } + + // Nested class for SHA3-384withRSA signatures + public static final class SHA3_384withRSA extends RSASignature { + public SHA3_384withRSA() { + super("SHA3-384", AlgorithmId.SHA3_384_oid, 11); + } + } + + // Nested class for SHA3-512withRSA signatures + public static final class SHA3_512withRSA extends RSASignature { + public SHA3_512withRSA() { + super("SHA3-512", AlgorithmId.SHA3_512_oid, 11); + } + } } diff --git a/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java b/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java index f3edf4f25e1..ca79f25cc44 100644 --- a/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java +++ b/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java @@ -84,6 +84,14 @@ public SunRsaSignEntries(Provider p) { "sun.security.rsa.RSASignature$SHA512_224withRSA", attrs); addA(p, "Signature", "SHA512/256withRSA", "sun.security.rsa.RSASignature$SHA512_256withRSA", attrs); + addA(p, "Signature", "SHA3-224withRSA", + "sun.security.rsa.RSASignature$SHA3_224withRSA", attrs); + addA(p, "Signature", "SHA3-256withRSA", + "sun.security.rsa.RSASignature$SHA3_256withRSA", attrs); + addA(p, "Signature", "SHA3-384withRSA", + "sun.security.rsa.RSASignature$SHA3_384withRSA", attrs); + addA(p, "Signature", "SHA3-512withRSA", + "sun.security.rsa.RSASignature$SHA3_512withRSA", attrs); addA(p, "KeyFactory", "RSASSA-PSS", "sun.security.rsa.RSAKeyFactory$PSS", attrs); @@ -92,7 +100,7 @@ public SunRsaSignEntries(Provider p) { addA(p, "Signature", "RSASSA-PSS", "sun.security.rsa.RSAPSSSignature", attrs); addA(p, "AlgorithmParameters", "RSASSA-PSS", - "sun.security.rsa.PSSParameters", attrs); + "sun.security.rsa.PSSParameters", null); } public Iterator<Provider.Service> iterator() { diff --git a/src/java.base/share/classes/sun/security/util/KnownOIDs.java b/src/java.base/share/classes/sun/security/util/KnownOIDs.java index f7eff259c4b..ac519dc2886 100644 --- a/src/java.base/share/classes/sun/security/util/KnownOIDs.java +++ b/src/java.base/share/classes/sun/security/util/KnownOIDs.java @@ -154,6 +154,14 @@ public enum KnownOIDs { SHA256withDSA("2.16.840.1.101.3.4.3.2"), SHA384withDSA("2.16.840.1.101.3.4.3.3"), SHA512withDSA("2.16.840.1.101.3.4.3.4"), + SHA3_224withDSA("2.16.840.1.101.3.4.3.5", "SHA3-224withDSA"), + SHA3_256withDSA("2.16.840.1.101.3.4.3.6", "SHA3-256withDSA"), + SHA3_384withDSA("2.16.840.1.101.3.4.3.7", "SHA3-384withDSA"), + SHA3_512withDSA("2.16.840.1.101.3.4.3.8", "SHA3-512withDSA"), + SHA3_224withECDSA("2.16.840.1.101.3.4.3.9", "SHA3-224withECDSA"), + SHA3_256withECDSA("2.16.840.1.101.3.4.3.10", "SHA3-256withECDSA"), + SHA3_384withECDSA("2.16.840.1.101.3.4.3.11", "SHA3-384withECDSA"), + SHA3_512withECDSA("2.16.840.1.101.3.4.3.12", "SHA3-512withECDSA"), SHA3_224withRSA("2.16.840.1.101.3.4.3.13", "SHA3-224withRSA"), SHA3_256withRSA("2.16.840.1.101.3.4.3.14", "SHA3-256withRSA"), SHA3_384withRSA("2.16.840.1.101.3.4.3.15", "SHA3-384withRSA"), @@ -429,9 +437,9 @@ public static KnownOIDs findMatch(String s) { if (debug != null) { debug.println("Setting up name2enum:"); } - List.of(KnownOIDs.values()).forEach(o -> { + for (KnownOIDs o : KnownOIDs.values()) { register(o); - }); + }; } private static void register(KnownOIDs o) { diff --git a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java index 8351bfa8168..b9b96b31c91 100644 --- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java +++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java @@ -196,6 +196,10 @@ public void derEncode (OutputStream out) throws IOException { algid.equals((Object)SHA512_oid) || algid.equals((Object)SHA512_224_oid) || algid.equals((Object)SHA512_256_oid) || + algid.equals((Object)SHA3_224_oid) || + algid.equals((Object)SHA3_256_oid) || + algid.equals((Object)SHA3_384_oid) || + algid.equals((Object)SHA3_512_oid) || algid.equals((Object)DSA_oid) || algid.equals((Object)sha1WithDSA_oid)) { ; // no parameter part encoded @@ -608,6 +612,18 @@ private static ConcurrentHashMap<String, String> collectOIDAliases() { public static final ObjectIdentifier SHA512_256_oid = ObjectIdentifier.of(KnownOIDs.SHA_512$256); + public static final ObjectIdentifier SHA3_224_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_224); + + public static final ObjectIdentifier SHA3_256_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_256); + + public static final ObjectIdentifier SHA3_384_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_384); + + public static final ObjectIdentifier SHA3_512_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_512); + public static final ObjectIdentifier DSA_oid = ObjectIdentifier.of(KnownOIDs.DSA); diff --git a/src/java.base/share/native/libjava/VM.c b/src/java.base/share/native/libjava/VM.c index 1cf694475da..ffc7e680014 100644 --- a/src/java.base/share/native/libjava/VM.c +++ b/src/java.base/share/native/libjava/VM.c @@ -62,6 +62,13 @@ Java_jdk_internal_misc_VM_initializeFromArchive(JNIEnv *env, jclass ignore, JVM_InitializeFromArchive(env, c); } +JNIEXPORT void JNICALL +Java_jdk_internal_misc_VM_defineArchivedModules(JNIEnv *env, jclass ignore, + jobject platform_loader, + jobject system_loader) { + JVM_DefineArchivedModules(env, platform_loader, system_loader); +} + JNIEXPORT jlong JNICALL Java_jdk_internal_misc_VM_getRandomSeedForCDSDump(JNIEnv *env, jclass ignore) { return JVM_GetRandomSeedForCDSDump(); diff --git a/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java b/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java index 9270df3745f..ac776f3f290 100644 --- a/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * 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,17 +50,19 @@ public class ForwardingFileObject<F extends FileObject> implements FileObject { protected final F fileObject; /** - * Creates a new instance of ForwardingFileObject. + * Creates a new instance of {@code ForwardingFileObject}. * @param fileObject delegate to this file object */ protected ForwardingFileObject(F fileObject) { this.fileObject = Objects.requireNonNull(fileObject); } + @Override public URI toUri() { return fileObject.toUri(); } + @Override public String getName() { return fileObject.getName(); } @@ -70,6 +72,7 @@ public String getName() { * @throws UnsupportedOperationException {@inheritDoc} * @throws IOException {@inheritDoc} */ + @Override public InputStream openInputStream() throws IOException { return fileObject.openInputStream(); } @@ -79,6 +82,7 @@ public InputStream openInputStream() throws IOException { * @throws UnsupportedOperationException {@inheritDoc} * @throws IOException {@inheritDoc} */ + @Override public OutputStream openOutputStream() throws IOException { return fileObject.openOutputStream(); } @@ -88,6 +92,7 @@ public OutputStream openOutputStream() throws IOException { * @throws UnsupportedOperationException {@inheritDoc} * @throws IOException {@inheritDoc} */ + @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { return fileObject.openReader(ignoreEncodingErrors); } @@ -97,6 +102,7 @@ public Reader openReader(boolean ignoreEncodingErrors) throws IOException { * @throws UnsupportedOperationException {@inheritDoc} * @throws IOException {@inheritDoc} */ + @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return fileObject.getCharContent(ignoreEncodingErrors); } @@ -106,14 +112,17 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept * @throws UnsupportedOperationException {@inheritDoc} * @throws IOException {@inheritDoc} */ + @Override public Writer openWriter() throws IOException { return fileObject.openWriter(); } + @Override public long getLastModified() { return fileObject.getLastModified(); } + @Override public boolean delete() { return fileObject.delete(); } diff --git a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java index 1a15c88c032..479c90e9ba9 100644 --- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 +49,7 @@ public class ForwardingJavaFileManager<M extends JavaFileManager> implements Jav protected final M fileManager; /** - * Creates a new instance of ForwardingJavaFileManager. + * Creates a new instance of {@code ForwardingJavaFileManager}. * @param fileManager delegate to this file manager */ protected ForwardingJavaFileManager(M fileManager) { @@ -60,6 +60,7 @@ protected ForwardingJavaFileManager(M fileManager) { * @throws SecurityException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ + @Override public ClassLoader getClassLoader(Location location) { return fileManager.getClassLoader(location); } @@ -68,6 +69,7 @@ public ClassLoader getClassLoader(Location location) { * @throws IOException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ + @Override public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, @@ -80,6 +82,7 @@ public Iterable<JavaFileObject> list(Location location, /** * @throws IllegalStateException {@inheritDoc} */ + @Override public String inferBinaryName(Location location, JavaFileObject file) { return fileManager.inferBinaryName(location, file); } @@ -87,6 +90,7 @@ public String inferBinaryName(Location location, JavaFileObject file) { /** * @throws IllegalArgumentException {@inheritDoc} */ + @Override public boolean isSameFile(FileObject a, FileObject b) { return fileManager.isSameFile(a, b); } @@ -95,14 +99,17 @@ public boolean isSameFile(FileObject a, FileObject b) { * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ + @Override public boolean handleOption(String current, Iterator<String> remaining) { return fileManager.handleOption(current, remaining); } + @Override public boolean hasLocation(Location location) { return fileManager.hasLocation(location); } + @Override public int isSupportedOption(String option) { return fileManager.isSupportedOption(option); } @@ -111,6 +118,7 @@ public int isSupportedOption(String option) { * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ + @Override public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) @@ -123,6 +131,7 @@ public JavaFileObject getJavaFileForInput(Location location, * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ + @Override public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, @@ -136,6 +145,7 @@ public JavaFileObject getJavaFileForOutput(Location location, * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ + @Override public FileObject getFileForInput(Location location, String packageName, String relativeName) @@ -148,6 +158,7 @@ public FileObject getFileForInput(Location location, * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ + @Override public FileObject getFileForOutput(Location location, String packageName, String relativeName, @@ -157,10 +168,12 @@ public FileObject getFileForOutput(Location location, return fileManager.getFileForOutput(location, packageName, relativeName, sibling); } + @Override public void flush() throws IOException { fileManager.flush(); } + @Override public void close() throws IOException { fileManager.close(); } @@ -169,6 +182,7 @@ public void close() throws IOException { * @since 9 * @spec JPMS */ + @Override public Location getLocationForModule(Location location, String moduleName) throws IOException { return fileManager.getLocationForModule(location, moduleName); } @@ -177,6 +191,7 @@ public Location getLocationForModule(Location location, String moduleName) throw * @since 9 * @spec JPMS */ + @Override public Location getLocationForModule(Location location, JavaFileObject fo) throws IOException { return fileManager.getLocationForModule(location, fo); } @@ -185,6 +200,7 @@ public Location getLocationForModule(Location location, JavaFileObject fo) throw * @since 9 * @spec JPMS */ + @Override public <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws IOException { return fileManager.getServiceLoader(location, service); } @@ -193,6 +209,7 @@ public <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service * @since 9 * @spec JPMS */ + @Override public String inferModuleName(Location location) throws IOException { return fileManager.inferModuleName(location); } @@ -201,6 +218,7 @@ public String inferModuleName(Location location) throws IOException { * @since 9 * @spec JPMS */ + @Override public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException { return fileManager.listLocationsForModules(location); } @@ -208,6 +226,7 @@ public Iterable<Set<Location>> listLocationsForModules(Location location) throws /** * @since 9 */ + @Override public boolean contains(Location location, FileObject fo) throws IOException { return fileManager.contains(location, fo); } diff --git a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java index b0b3e9d40fd..bf7ad8f70ad 100644 --- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,23 +43,27 @@ public class ForwardingJavaFileObject<F extends JavaFileObject> { /** - * Creates a new instance of ForwardingJavaFileObject. + * Creates a new instance of {@code ForwardingJavaFileObject}. * @param fileObject delegate to this file object */ protected ForwardingJavaFileObject(F fileObject) { super(fileObject); } + @Override public Kind getKind() { return fileObject.getKind(); } + @Override public boolean isNameCompatible(String simpleName, Kind kind) { return fileObject.isNameCompatible(simpleName, kind); } + @Override public NestingKind getNestingKind() { return fileObject.getNestingKind(); } + @Override public Modifier getAccessLevel() { return fileObject.getAccessLevel(); } } diff --git a/src/java.compiler/share/classes/javax/tools/JavaFileObject.java b/src/java.compiler/share/classes/javax/tools/JavaFileObject.java index 14a4fa9e698..48d6388df9e 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/JavaFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,8 +63,7 @@ enum Kind { CLASS(".class"), /** - * HTML files. For example, regular files ending with {@code - * .html}. + * HTML files. For example, regular files ending with {@code .html}. */ HTML(".html"), @@ -78,7 +77,7 @@ enum Kind { * empty string ({@code ""}) is used. */ public final String extension; - private Kind(String extension) { + Kind(String extension) { this.extension = Objects.requireNonNull(extension); } } @@ -94,12 +93,11 @@ private Kind(String extension) { * Checks if this file object is compatible with the specified * simple name and kind. A simple name is a single identifier * (not qualified) as defined in - * <cite>The Java Language Specification</cite>, - * section 6.2 "Names and Identifiers". + * <cite>The Java Language Specification</cite>, section {@jls 6.2}. * * @param simpleName a simple name of a class * @param kind a kind - * @return {@code true} if this file object is compatible; false + * @return {@code true} if this file object is compatible; {@code false} * otherwise */ boolean isNameCompatible(String simpleName, Kind kind); @@ -119,7 +117,7 @@ private Kind(String extension) { /** * Provides a hint about the access level of the class represented - * by this file object. If the access level is not known or if + * by this file object. If the access level is not known or * this file object does not represent a class file this method * returns {@code null}. * diff --git a/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java b/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java index a2905b91356..9c8d491996a 100644 --- a/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.util.Objects; import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; -import javax.tools.JavaFileObject.Kind; /** * Provides simple implementations for most methods in JavaFileObject. diff --git a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java index ab04e859795..2fee7e2673a 100644 --- a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ import java.util.List; /** - * File manager based on {@linkplain File java.io.File} and {@linkplain Path java.nio.file.Path}. + * File manager based on {@link File java.io.File} and {@link Path java.nio.file.Path}. * * A common way to obtain an instance of this class is using * {@linkplain JavaCompiler#getStandardFileManager getStandardFileManager}, for example: @@ -363,7 +363,7 @@ default void setLocationFromPaths(Location location, Collection<? extends Path> * * All such module-specific associations will be cancelled if a * new search path is associated with the location by calling - * {@linkplain #setLocation setLocation } or + * {@linkplain #setLocation setLocation} or * {@linkplain #setLocationFromPaths setLocationFromPaths}. * * @throws IllegalStateException if the location is not a module-oriented @@ -377,8 +377,8 @@ default void setLocationFromPaths(Location location, Collection<? extends Path> * @param moduleName the name of the module * @param paths the search path to associate with the location and module. * - * @see setLocation - * @see setLocationFromPaths + * @see #setLocation + * @see #setLocationFromPaths * * @since 9 */ @@ -480,8 +480,8 @@ default void setPathFactory(PathFactory f) { } private static Iterable<Path> asPaths(final Iterable<? extends File> files) { - return () -> new Iterator<Path>() { - Iterator<? extends File> iter = files.iterator(); + return () -> new Iterator<>() { + final Iterator<? extends File> iter = files.iterator(); @Override public boolean hasNext() { @@ -496,8 +496,8 @@ public Path next() { } private static Iterable<File> asFiles(final Iterable<? extends Path> paths) { - return () -> new Iterator<File>() { - Iterator<? extends Path> iter = paths.iterator(); + return () -> new Iterator<>() { + final Iterator<? extends Path> iter = paths.iterator(); @Override public boolean hasNext() { diff --git a/src/java.compiler/share/classes/javax/tools/package-info.java b/src/java.compiler/share/classes/javax/tools/package-info.java index e7883f9be74..c5ec54e7871 100644 --- a/src/java.compiler/share/classes/javax/tools/package-info.java +++ b/src/java.compiler/share/classes/javax/tools/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * 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,25 +32,25 @@ * but there is no requirement to provide any tools implementing them. * * <p>Unless explicitly allowed, all methods in this package might - * throw a {@linkplain java.lang.NullPointerException} if given a + * throw a {@link java.lang.NullPointerException} if given a * {@code null} argument or if given a * {@linkplain java.lang.Iterable list or collection} containing * {@code null} elements. Similarly, no method may return * {@code null} unless explicitly allowed. * - * <p>This package is the home of the Java programming language compiler framework. This - * framework allows clients of the framework to locate and run + * <p>This package is the home of the Java programming language compiler framework. + * This framework allows clients of the framework to locate and run * compilers from programs. The framework also provides Service * Provider Interfaces (SPI) for structured access to diagnostics - * ({@linkplain javax.tools.DiagnosticListener}) as well as a file - * abstraction for overriding file access ({@linkplain - * javax.tools.JavaFileManager} and {@linkplain - * javax.tools.JavaFileObject}). See {@linkplain + * ({@link javax.tools.DiagnosticListener}) as well as a file + * abstraction for overriding file access ({@link + * javax.tools.JavaFileManager} and {@link + * javax.tools.JavaFileObject}). See {@link * javax.tools.JavaCompiler} for more details on using the SPI. * * <p>There is no requirement for a compiler at runtime. However, if * a default compiler is provided, it can be located using the - * {@linkplain javax.tools.ToolProvider}, for example: + * {@link javax.tools.ToolProvider}, for example: * * <p>{@code JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();} * diff --git a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java index 04d32e6d959..2b0fdd98d60 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -333,7 +333,7 @@ public void read(byte[] b, int off, int len, long pos) } long index = pos/BUFFER_LENGTH; - int offset = (int)pos % BUFFER_LENGTH; + int offset = (int)(pos % BUFFER_LENGTH); while (len > 0) { int nbytes = Math.min(len, BUFFER_LENGTH - offset); byte[] buf = getCacheBlock(index++); diff --git a/src/java.desktop/share/classes/javax/swing/Box.java b/src/java.desktop/share/classes/javax/swing/Box.java index 9db52ce9a0e..85983abddc1 100644 --- a/src/java.desktop/share/classes/javax/swing/Box.java +++ b/src/java.desktop/share/classes/javax/swing/Box.java @@ -316,6 +316,7 @@ public Filler(Dimension min, Dimension pref, Dimension max) { setMinimumSize(min); setPreferredSize(pref); setMaximumSize(max); + setFocusable(false); } /** diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/DefaultLdapDnsProvider.java b/src/java.naming/share/classes/com/sun/jndi/ldap/DefaultLdapDnsProvider.java index cdb77128357..ef587bca480 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/DefaultLdapDnsProvider.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/DefaultLdapDnsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * 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,14 +25,14 @@ package com.sun.jndi.ldap; -import javax.naming.NamingException; -import javax.naming.ldap.spi.LdapDnsProvider; -import javax.naming.ldap.spi.LdapDnsProviderResult; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; +import javax.naming.NamingException; +import javax.naming.ldap.spi.LdapDnsProviderResult; + public class DefaultLdapDnsProvider { public Optional<LdapDnsProviderResult> lookupEndpoints(String url, @@ -82,5 +82,4 @@ public Optional<LdapDnsProviderResult> lookupEndpoints(String url, return Optional.of(res); } } - } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapDnsProviderService.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapDnsProviderService.java index 1d6ac817f0b..b5f6fd05c11 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapDnsProviderService.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapDnsProviderService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ static LdapDnsProviderService getInstance() { * subclasses of {@code LdapDnsProvider} then this method will fall back * to the {@code DefaultLdapDnsProvider}. * - * @throws NamingException if the {@code url} in not valid or an error + * @throws NamingException if the {@code url} is not valid or an error * occurred while performing the lookup. */ LdapDnsProviderResult lookupEndpoints(String url, Hashtable<?,?> env) @@ -110,5 +110,4 @@ LdapDnsProviderResult lookupEndpoints(String url, Hashtable<?,?> env) } return result; } - } diff --git a/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProvider.java b/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProvider.java index abafef64685..d89436f188a 100644 --- a/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProvider.java +++ b/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,5 +105,4 @@ private static Void checkPermission() { */ public abstract Optional<LdapDnsProviderResult> lookupEndpoints( String url, Map<?,?> env) throws NamingException; - } diff --git a/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProviderResult.java b/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProviderResult.java index d28326bb7e7..9427c256c26 100644 --- a/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProviderResult.java +++ b/src/java.naming/share/classes/javax/naming/ldap/spi/LdapDnsProviderResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 +32,7 @@ * * <p> This class is used by an {@link LdapDnsProvider} to return the result * of a DNS lookup for a given LDAP URL. The result consists of a domain name - * and its associated ldap server endpoints. + * and its associated LDAP server endpoints. * * <p> A {@code null} {@code domainName} is equivalent to and represented * by an empty string. @@ -46,10 +46,10 @@ public final class LdapDnsProviderResult { /** * Construct an LdapDnsProviderResult consisting of a resolved domain name - * and the ldap server endpoints that serve the domain. + * and the LDAP server endpoints that serve the domain. * * @param domainName the resolved domain name; can be null. - * @param endpoints the possibly empty list of resolved ldap server + * @param endpoints the possibly empty list of resolved LDAP server * endpoints * * @throws NullPointerException if {@code endpoints} contains {@code null} @@ -63,7 +63,7 @@ public LdapDnsProviderResult(String domainName, List<String> endpoints) { } /** - * Returns the domain name resolved from the ldap URL. This method returns + * Returns the domain name resolved from the LDAP URL. This method returns * the empty string if the {@code LdapDnsProviderResult} is created with a * null domain name. * @@ -75,13 +75,12 @@ public String getDomainName() { /** * Returns the possibly empty list of individual server endpoints resolved - * from the ldap URL. + * from the LDAP URL. * * @return a possibly empty unmodifiable {@link List} containing the - * resolved ldap server endpoints + * resolved LDAP server endpoints */ public List<String> getEndpoints() { return endpoints; } - } diff --git a/src/java.xml/share/classes/org/w3c/dom/package-info.java b/src/java.xml/share/classes/org/w3c/dom/package-info.java index 8d08de006fd..10f081415ed 100644 --- a/src/java.xml/share/classes/org/w3c/dom/package-info.java +++ b/src/java.xml/share/classes/org/w3c/dom/package-info.java @@ -42,31 +42,6 @@ * {@link org.w3c.dom.Node#setTextContent(String) setTextContent} shared the same * content that defined the TextContent property itself. * - * @implNote - * The JDK implementation of {@link org.w3c.dom.ls.LSSerializer LSSerializer} - * follows the <a href="https://www.w3.org/TR/xml/#charsets">Characters</a> section - * of the XML Specification in handling characters output. In particular, the - * specification defined a character range that excluded the surrogate blocks. - * As a result, the JDK LSSerializer writes characters in the surrogate blocks - * as Character References. Character {@code 0xf0 0x9f 0x9a 0xa9} - * (Unicode code point U+1F6A9) for example will be written as {@code 🚩}. - * - * <p> - * This behavior is different from what was in the class description of - * {@link org.w3c.dom.ls.LSSerializer LSSerializer}. The relevant section is quoted - * below: - * - * <p> - * {@code Within the character data of a document (outside of markup), any characters - * that cannot be represented directly are replaced with character references... - * Any characters that cannot be represented directly in the output character encoding - * are serialized as numeric character references } - * - * <p> - * The JDK implementation does not follow this definition because it is not consistent - * with the XML Specification that defined an explicit character range with no - * association to the setting of the output character encoding. - * * * @since 1.4 */ diff --git a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocRootTree.java b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocRootTree.java index 4565cefd70b..427425a526e 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocRootTree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocRootTree.java @@ -26,10 +26,10 @@ package com.sun.source.doctree; /** - * A tree node for an {@code @docroot} inline tag. + * A tree node for an {@code @docRoot} inline tag. * * <pre> - * {@docroot} + * {@docRoot} * </pre> * * @since 1.8 diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/DeconstructionPatternTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/DeconstructionPatternTree.java new file mode 100644 index 00000000000..fac342afc11 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/DeconstructionPatternTree.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. 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.source.tree; + +import java.util.List; + +/** + * {@preview Associated with pattern matching for instanceof, a preview feature of + * the Java language. + * + * This interface is associated with <i>pattern matching for instanceof</i>, a preview + * feature of the Java language. Preview features + * may be removed in a future release, or upgraded to permanent + * features of the Java language.} + * + * A deconstruction pattern tree + * + * @since 15 + */ +public interface DeconstructionPatternTree extends PatternTree { + + /** + * Returns the deconstructed type. + * @return the deconstructed type + */ + Tree getDeconstructor(); + + /** + * Returns the nested patterns. + * @return the nested patterns. + */ + List<? extends PatternTree> getNestedPatterns(); + +} + diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java index f368973b550..b3215244f2c 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java @@ -234,6 +234,21 @@ public enum Kind { */ BINDING_PATTERN(BindingPatternTree.class), + /** + * {@preview Associated with pattern matching for instanceof, a preview feature of + * the Java language. + * + * This enum constant is associated with <i>pattern matching for instanceof</i>, a preview + * feature of the Java language. Preview features + * may be removed in a future release, or upgraded to permanent + * features of the Java language.} + * + * Used for instances of {@link DeconstructionPatternTree}. + * + * @since 15 + */ + DECONSTRUCTION_PATTERN(DeconstructionPatternTree.class), + /** * Used for instances of {@link PrimitiveTypeTree}. */ diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java index 1fb0b0a6aae..eb752d6982b 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java @@ -274,6 +274,23 @@ public interface TreeVisitor<R,P> { */ R visitBindingPattern(BindingPatternTree node, P p); + /** + * {@preview Associated with pattern matching for instanceof, a preview feature of + * the Java language. + * + * This method is associated with <i>pattern matching for instanceof</i>, a preview + * feature of the Java language. Preview features + * may be removed in a future release, or upgraded to permanent + * features of the Java language.} + * + * Visits an DeconstructionPatternTree node. + * @param node the node being visited + * @param p a parameter value + * @return a result value + * @since 15 + */ + R visitDeconstructionPattern(DeconstructionPatternTree node, P p); + /** * Visits a MethodTree node. * @param node the node being visited diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java b/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java index 8878486b99d..54dc3d259bd 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java @@ -137,7 +137,7 @@ DocCommentTree newDocCommentTree(List<? extends DocTree> fullBody, List<? extends DocTree> preamble, List<? extends DocTree> postamble); /** - * Creates a new {@code DocRootTree} object, to represent an {@code {@docroot}} tag. + * Creates a new {@code DocRootTree} object, to represent an {@code {@docRoot}} tag. * @return a {@code DocRootTree} object */ DocRootTree newDocRootTree(); diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java b/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java index 2c183e17d9a..60fd4b28675 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java @@ -39,6 +39,8 @@ import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.EntityTree; +import com.sun.source.tree.CompilationUnitTree; /** * Provides access to syntax trees for doc comments. @@ -202,19 +204,17 @@ public static DocTrees instance(ProcessingEnvironment env) { * @param root the compilation unit that contains tree */ public abstract void printMessage(Diagnostic.Kind kind, CharSequence msg, - com.sun.source.doctree.DocTree t, - com.sun.source.doctree.DocCommentTree c, - com.sun.source.tree.CompilationUnitTree root); + DocTree t, DocCommentTree c, CompilationUnitTree root); /** * Sets the break iterator to compute the first sentence of * documentation comments. - * @param breakiterator a break iterator or {@code null} to specify the default + * @param breakIterator a break iterator or {@code null} to specify the default * sentence breaker * * @since 9 */ - public abstract void setBreakIterator(BreakIterator breakiterator); + public abstract void setBreakIterator(BreakIterator breakIterator); /** * Returns a utility object for creating {@code DocTree} objects. @@ -223,4 +223,16 @@ public abstract void printMessage(Diagnostic.Kind kind, CharSequence msg, * @since 9 */ public abstract DocTreeFactory getDocTreeFactory(); + + /** + * Returns a string containing the characters for the entity in a given entity tree, + * or {@code null} if the tree does not represent a valid series of characters. + * + * <p>The interpretation of entities is based on section + * <a href="https://www.w3.org/TR/html52/syntax.html#character-references">8.1.4. Character references</a> + * in the HTML 5.2 specification.</p> + * + * @return a string containing the characters + */ + public abstract String getCharacters(EntityTree tree); } diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java index 03ff696a980..47ecb1e2dc1 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java @@ -564,6 +564,19 @@ public R visitBindingPattern(BindingPatternTree node, P p) { return defaultAction(node, p); } + /** + * {@inheritDoc} This implementation calls {@code defaultAction}. + * + * @param node {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of {@code defaultAction} + * @since 15 + */ + @Override + public R visitDeconstructionPattern(DeconstructionPatternTree node, P p) { + return defaultAction(node, p); + } + /** * {@inheritDoc} This implementation calls {@code defaultAction}. * diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java index e7cff68e384..e2a5a50ea2c 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java @@ -694,6 +694,20 @@ public R visitBindingPattern(BindingPatternTree node, P p) { return scan(node.getType(), p); } + /** + * {@inheritDoc} This implementation scans the children in left to right order. + * + * @param node {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of scanning + * @since 15 + */ + @Override + public R visitDeconstructionPattern(DeconstructionPatternTree node, P p) { + R r = scan(node.getDeconstructor(), p); + return scanAndReduce(node.getNestedPatterns(), p, r); + } + /** * {@inheritDoc} This implementation scans the children in left to right order. * diff --git a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java index c40d4bb52e8..0754d0063d3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -295,18 +295,12 @@ public Void visitText(TextTree tree, Void ignore) { public Void visitEntity(EntityTree tree, Void ignore) { checkAllowsText(tree); markEnclosingTag(Flag.HAS_TEXT); - String name = tree.getName().toString(); - if (name.startsWith("#")) { - int v = StringUtils.toLowerCase(name).startsWith("#x") - ? Integer.parseInt(name.substring(2), 16) - : Integer.parseInt(name.substring(1), 10); - if (!Entity.isValid(v)) { - env.messages.error(HTML, tree, "dc.entity.invalid", name); - } - } else if (!Entity.isValid(name)) { - env.messages.error(HTML, tree, "dc.entity.invalid", name); + String s = env.trees.getCharacters(tree); + if (s == null) { + env.messages.error(HTML, tree, "dc.entity.invalid", tree.getName()); } return null; + } void checkAllowsText(DocTree tree) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Entity.java b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Entity.java deleted file mode 100644 index ca6368af592..00000000000 --- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Entity.java +++ /dev/null @@ -1,2188 +0,0 @@ -/* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.tools.doclint; - -import java.util.HashMap; - -/** - * Table of entities defined in HTML 5.2. - * - * <p> Derived from the - * <a href="https://www.w3.org/TR/html52/syntax.html#named-character-references">Named character references</a> - * section of the HTML 5.2 specification. - * - * <p><b>This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.</b></p> - */ -public class Entity { - - private static final HashMap<String,String> html5Entities = new HashMap<>(); - - static { - html5Entities.put("Aacute", "\u00C1"); - html5Entities.put("aacute", "\u00E1"); - html5Entities.put("Abreve", "\u0102"); - html5Entities.put("abreve", "\u0103"); - html5Entities.put("ac", "\u223E"); - html5Entities.put("acd", "\u223F"); - html5Entities.put("acE", "\u223E\u0333"); - html5Entities.put("Acirc", "\u00C2"); - html5Entities.put("acirc", "\u00E2"); - html5Entities.put("acute", "\u00B4"); - html5Entities.put("Acy", "\u0410"); - html5Entities.put("acy", "\u0430"); - html5Entities.put("AElig", "\u00C6"); - html5Entities.put("aelig", "\u00E6"); - html5Entities.put("af", "\u2061"); - html5Entities.put("Afr", "\uD835\uDD04"); - html5Entities.put("afr", "\uD835\uDD1E"); - html5Entities.put("Agrave", "\u00C0"); - html5Entities.put("agrave", "\u00E0"); - html5Entities.put("alefsym", "\u2135"); - html5Entities.put("aleph", "\u2135"); - html5Entities.put("Alpha", "\u0391"); - html5Entities.put("alpha", "\u03B1"); - html5Entities.put("Amacr", "\u0100"); - html5Entities.put("amacr", "\u0101"); - html5Entities.put("amalg", "\u2A3F"); - html5Entities.put("amp", "\u0026"); - html5Entities.put("AMP", "\u0026"); - html5Entities.put("andand", "\u2A55"); - html5Entities.put("And", "\u2A53"); - html5Entities.put("and", "\u2227"); - html5Entities.put("andd", "\u2A5C"); - html5Entities.put("andslope", "\u2A58"); - html5Entities.put("andv", "\u2A5A"); - html5Entities.put("ang", "\u2220"); - html5Entities.put("ange", "\u29A4"); - html5Entities.put("angle", "\u2220"); - html5Entities.put("angmsdaa", "\u29A8"); - html5Entities.put("angmsdab", "\u29A9"); - html5Entities.put("angmsdac", "\u29AA"); - html5Entities.put("angmsdad", "\u29AB"); - html5Entities.put("angmsdae", "\u29AC"); - html5Entities.put("angmsdaf", "\u29AD"); - html5Entities.put("angmsdag", "\u29AE"); - html5Entities.put("angmsdah", "\u29AF"); - html5Entities.put("angmsd", "\u2221"); - html5Entities.put("angrt", "\u221F"); - html5Entities.put("angrtvb", "\u22BE"); - html5Entities.put("angrtvbd", "\u299D"); - html5Entities.put("angsph", "\u2222"); - html5Entities.put("angst", "\u00C5"); - html5Entities.put("angzarr", "\u237C"); - html5Entities.put("Aogon", "\u0104"); - html5Entities.put("aogon", "\u0105"); - html5Entities.put("Aopf", "\uD835\uDD38"); - html5Entities.put("aopf", "\uD835\uDD52"); - html5Entities.put("apacir", "\u2A6F"); - html5Entities.put("ap", "\u2248"); - html5Entities.put("apE", "\u2A70"); - html5Entities.put("ape", "\u224A"); - html5Entities.put("apid", "\u224B"); - html5Entities.put("apos", "\u0027"); - html5Entities.put("ApplyFunction", "\u2061"); - html5Entities.put("approx", "\u2248"); - html5Entities.put("approxeq", "\u224A"); - html5Entities.put("Aring", "\u00C5"); - html5Entities.put("aring", "\u00E5"); - html5Entities.put("Ascr", "\uD835\uDC9C"); - html5Entities.put("ascr", "\uD835\uDCB6"); - html5Entities.put("Assign", "\u2254"); - html5Entities.put("ast", "\u002A"); - html5Entities.put("asymp", "\u2248"); - html5Entities.put("asympeq", "\u224D"); - html5Entities.put("Atilde", "\u00C3"); - html5Entities.put("atilde", "\u00E3"); - html5Entities.put("Auml", "\u00C4"); - html5Entities.put("auml", "\u00E4"); - html5Entities.put("awconint", "\u2233"); - html5Entities.put("awint", "\u2A11"); - html5Entities.put("backcong", "\u224C"); - html5Entities.put("backepsilon", "\u03F6"); - html5Entities.put("backprime", "\u2035"); - html5Entities.put("backsim", "\u223D"); - html5Entities.put("backsimeq", "\u22CD"); - html5Entities.put("Backslash", "\u2216"); - html5Entities.put("Barv", "\u2AE7"); - html5Entities.put("barvee", "\u22BD"); - html5Entities.put("barwed", "\u2305"); - html5Entities.put("Barwed", "\u2306"); - html5Entities.put("barwedge", "\u2305"); - html5Entities.put("bbrk", "\u23B5"); - html5Entities.put("bbrktbrk", "\u23B6"); - html5Entities.put("bcong", "\u224C"); - html5Entities.put("Bcy", "\u0411"); - html5Entities.put("bcy", "\u0431"); - html5Entities.put("bdquo", "\u201E"); - html5Entities.put("becaus", "\u2235"); - html5Entities.put("because", "\u2235"); - html5Entities.put("Because", "\u2235"); - html5Entities.put("bemptyv", "\u29B0"); - html5Entities.put("bepsi", "\u03F6"); - html5Entities.put("bernou", "\u212C"); - html5Entities.put("Bernoullis", "\u212C"); - html5Entities.put("Beta", "\u0392"); - html5Entities.put("beta", "\u03B2"); - html5Entities.put("beth", "\u2136"); - html5Entities.put("between", "\u226C"); - html5Entities.put("Bfr", "\uD835\uDD05"); - html5Entities.put("bfr", "\uD835\uDD1F"); - html5Entities.put("bigcap", "\u22C2"); - html5Entities.put("bigcirc", "\u25EF"); - html5Entities.put("bigcup", "\u22C3"); - html5Entities.put("bigodot", "\u2A00"); - html5Entities.put("bigoplus", "\u2A01"); - html5Entities.put("bigotimes", "\u2A02"); - html5Entities.put("bigsqcup", "\u2A06"); - html5Entities.put("bigstar", "\u2605"); - html5Entities.put("bigtriangledown", "\u25BD"); - html5Entities.put("bigtriangleup", "\u25B3"); - html5Entities.put("biguplus", "\u2A04"); - html5Entities.put("bigvee", "\u22C1"); - html5Entities.put("bigwedge", "\u22C0"); - html5Entities.put("bkarow", "\u290D"); - html5Entities.put("blacklozenge", "\u29EB"); - html5Entities.put("blacksquare", "\u25AA"); - html5Entities.put("blacktriangle", "\u25B4"); - html5Entities.put("blacktriangledown", "\u25BE"); - html5Entities.put("blacktriangleleft", "\u25C2"); - html5Entities.put("blacktriangleright", "\u25B8"); - html5Entities.put("blank", "\u2423"); - html5Entities.put("blk12", "\u2592"); - html5Entities.put("blk14", "\u2591"); - html5Entities.put("blk34", "\u2593"); - html5Entities.put("block", "\u2588"); - html5Entities.put("bne", "\u003D\u20E5"); - html5Entities.put("bnequiv", "\u2261\u20E5"); - html5Entities.put("bNot", "\u2AED"); - html5Entities.put("bnot", "\u2310"); - html5Entities.put("Bopf", "\uD835\uDD39"); - html5Entities.put("bopf", "\uD835\uDD53"); - html5Entities.put("bot", "\u22A5"); - html5Entities.put("bottom", "\u22A5"); - html5Entities.put("bowtie", "\u22C8"); - html5Entities.put("boxbox", "\u29C9"); - html5Entities.put("boxdl", "\u2510"); - html5Entities.put("boxdL", "\u2555"); - html5Entities.put("boxDl", "\u2556"); - html5Entities.put("boxDL", "\u2557"); - html5Entities.put("boxdr", "\u250C"); - html5Entities.put("boxdR", "\u2552"); - html5Entities.put("boxDr", "\u2553"); - html5Entities.put("boxDR", "\u2554"); - html5Entities.put("boxh", "\u2500"); - html5Entities.put("boxH", "\u2550"); - html5Entities.put("boxhd", "\u252C"); - html5Entities.put("boxHd", "\u2564"); - html5Entities.put("boxhD", "\u2565"); - html5Entities.put("boxHD", "\u2566"); - html5Entities.put("boxhu", "\u2534"); - html5Entities.put("boxHu", "\u2567"); - html5Entities.put("boxhU", "\u2568"); - html5Entities.put("boxHU", "\u2569"); - html5Entities.put("boxminus", "\u229F"); - html5Entities.put("boxplus", "\u229E"); - html5Entities.put("boxtimes", "\u22A0"); - html5Entities.put("boxul", "\u2518"); - html5Entities.put("boxuL", "\u255B"); - html5Entities.put("boxUl", "\u255C"); - html5Entities.put("boxUL", "\u255D"); - html5Entities.put("boxur", "\u2514"); - html5Entities.put("boxuR", "\u2558"); - html5Entities.put("boxUr", "\u2559"); - html5Entities.put("boxUR", "\u255A"); - html5Entities.put("boxv", "\u2502"); - html5Entities.put("boxV", "\u2551"); - html5Entities.put("boxvh", "\u253C"); - html5Entities.put("boxvH", "\u256A"); - html5Entities.put("boxVh", "\u256B"); - html5Entities.put("boxVH", "\u256C"); - html5Entities.put("boxvl", "\u2524"); - html5Entities.put("boxvL", "\u2561"); - html5Entities.put("boxVl", "\u2562"); - html5Entities.put("boxVL", "\u2563"); - html5Entities.put("boxvr", "\u251C"); - html5Entities.put("boxvR", "\u255E"); - html5Entities.put("boxVr", "\u255F"); - html5Entities.put("boxVR", "\u2560"); - html5Entities.put("bprime", "\u2035"); - html5Entities.put("breve", "\u02D8"); - html5Entities.put("Breve", "\u02D8"); - html5Entities.put("brvbar", "\u00A6"); - html5Entities.put("bscr", "\uD835\uDCB7"); - html5Entities.put("Bscr", "\u212C"); - html5Entities.put("bsemi", "\u204F"); - html5Entities.put("bsim", "\u223D"); - html5Entities.put("bsime", "\u22CD"); - html5Entities.put("bsolb", "\u29C5"); - html5Entities.put("bsol", "\\"); - html5Entities.put("bsolhsub", "\u27C8"); - html5Entities.put("bull", "\u2022"); - html5Entities.put("bullet", "\u2022"); - html5Entities.put("bump", "\u224E"); - html5Entities.put("bumpE", "\u2AAE"); - html5Entities.put("bumpe", "\u224F"); - html5Entities.put("Bumpeq", "\u224E"); - html5Entities.put("bumpeq", "\u224F"); - html5Entities.put("Cacute", "\u0106"); - html5Entities.put("cacute", "\u0107"); - html5Entities.put("capand", "\u2A44"); - html5Entities.put("capbrcup", "\u2A49"); - html5Entities.put("capcap", "\u2A4B"); - html5Entities.put("cap", "\u2229"); - html5Entities.put("Cap", "\u22D2"); - html5Entities.put("capcup", "\u2A47"); - html5Entities.put("capdot", "\u2A40"); - html5Entities.put("CapitalDifferentialD", "\u2145"); - html5Entities.put("caps", "\u2229\uFE00"); - html5Entities.put("caret", "\u2041"); - html5Entities.put("caron", "\u02C7"); - html5Entities.put("Cayleys", "\u212D"); - html5Entities.put("ccaps", "\u2A4D"); - html5Entities.put("Ccaron", "\u010C"); - html5Entities.put("ccaron", "\u010D"); - html5Entities.put("Ccedil", "\u00C7"); - html5Entities.put("ccedil", "\u00E7"); - html5Entities.put("Ccirc", "\u0108"); - html5Entities.put("ccirc", "\u0109"); - html5Entities.put("Cconint", "\u2230"); - html5Entities.put("ccups", "\u2A4C"); - html5Entities.put("ccupssm", "\u2A50"); - html5Entities.put("Cdot", "\u010A"); - html5Entities.put("cdot", "\u010B"); - html5Entities.put("cedil", "\u00B8"); - html5Entities.put("Cedilla", "\u00B8"); - html5Entities.put("cemptyv", "\u29B2"); - html5Entities.put("cent", "\u00A2"); - html5Entities.put("centerdot", "\u00B7"); - html5Entities.put("CenterDot", "\u00B7"); - html5Entities.put("cfr", "\uD835\uDD20"); - html5Entities.put("Cfr", "\u212D"); - html5Entities.put("CHcy", "\u0427"); - html5Entities.put("chcy", "\u0447"); - html5Entities.put("check", "\u2713"); - html5Entities.put("checkmark", "\u2713"); - html5Entities.put("Chi", "\u03A7"); - html5Entities.put("chi", "\u03C7"); - html5Entities.put("circ", "\u02C6"); - html5Entities.put("circeq", "\u2257"); - html5Entities.put("circlearrowleft", "\u21BA"); - html5Entities.put("circlearrowright", "\u21BB"); - html5Entities.put("circledast", "\u229B"); - html5Entities.put("circledcirc", "\u229A"); - html5Entities.put("circleddash", "\u229D"); - html5Entities.put("CircleDot", "\u2299"); - html5Entities.put("circledR", "\u00AE"); - html5Entities.put("circledS", "\u24C8"); - html5Entities.put("CircleMinus", "\u2296"); - html5Entities.put("CirclePlus", "\u2295"); - html5Entities.put("CircleTimes", "\u2297"); - html5Entities.put("cir", "\u25CB"); - html5Entities.put("cirE", "\u29C3"); - html5Entities.put("cire", "\u2257"); - html5Entities.put("cirfnint", "\u2A10"); - html5Entities.put("cirmid", "\u2AEF"); - html5Entities.put("cirscir", "\u29C2"); - html5Entities.put("ClockwiseContourIntegral", "\u2232"); - html5Entities.put("CloseCurlyDoubleQuote", "\u201D"); - html5Entities.put("CloseCurlyQuote", "\u2019"); - html5Entities.put("clubs", "\u2663"); - html5Entities.put("clubsuit", "\u2663"); - html5Entities.put("colon", "\u003A"); - html5Entities.put("Colon", "\u2237"); - html5Entities.put("Colone", "\u2A74"); - html5Entities.put("colone", "\u2254"); - html5Entities.put("coloneq", "\u2254"); - html5Entities.put("comma", "\u002C"); - html5Entities.put("commat", "\u0040"); - html5Entities.put("comp", "\u2201"); - html5Entities.put("compfn", "\u2218"); - html5Entities.put("complement", "\u2201"); - html5Entities.put("complexes", "\u2102"); - html5Entities.put("cong", "\u2245"); - html5Entities.put("congdot", "\u2A6D"); - html5Entities.put("Congruent", "\u2261"); - html5Entities.put("conint", "\u222E"); - html5Entities.put("Conint", "\u222F"); - html5Entities.put("ContourIntegral", "\u222E"); - html5Entities.put("copf", "\uD835\uDD54"); - html5Entities.put("Copf", "\u2102"); - html5Entities.put("coprod", "\u2210"); - html5Entities.put("Coproduct", "\u2210"); - html5Entities.put("copy", "\u00A9"); - html5Entities.put("COPY", "\u00A9"); - html5Entities.put("copysr", "\u2117"); - html5Entities.put("CounterClockwiseContourIntegral", "\u2233"); - html5Entities.put("crarr", "\u21B5"); - html5Entities.put("cross", "\u2717"); - html5Entities.put("Cross", "\u2A2F"); - html5Entities.put("Cscr", "\uD835\uDC9E"); - html5Entities.put("cscr", "\uD835\uDCB8"); - html5Entities.put("csub", "\u2ACF"); - html5Entities.put("csube", "\u2AD1"); - html5Entities.put("csup", "\u2AD0"); - html5Entities.put("csupe", "\u2AD2"); - html5Entities.put("ctdot", "\u22EF"); - html5Entities.put("cudarrl", "\u2938"); - html5Entities.put("cudarrr", "\u2935"); - html5Entities.put("cuepr", "\u22DE"); - html5Entities.put("cuesc", "\u22DF"); - html5Entities.put("cularr", "\u21B6"); - html5Entities.put("cularrp", "\u293D"); - html5Entities.put("cupbrcap", "\u2A48"); - html5Entities.put("cupcap", "\u2A46"); - html5Entities.put("CupCap", "\u224D"); - html5Entities.put("cup", "\u222A"); - html5Entities.put("Cup", "\u22D3"); - html5Entities.put("cupcup", "\u2A4A"); - html5Entities.put("cupdot", "\u228D"); - html5Entities.put("cupor", "\u2A45"); - html5Entities.put("cups", "\u222A\uFE00"); - html5Entities.put("curarr", "\u21B7"); - html5Entities.put("curarrm", "\u293C"); - html5Entities.put("curlyeqprec", "\u22DE"); - html5Entities.put("curlyeqsucc", "\u22DF"); - html5Entities.put("curlyvee", "\u22CE"); - html5Entities.put("curlywedge", "\u22CF"); - html5Entities.put("curren", "\u00A4"); - html5Entities.put("curvearrowleft", "\u21B6"); - html5Entities.put("curvearrowright", "\u21B7"); - html5Entities.put("cuvee", "\u22CE"); - html5Entities.put("cuwed", "\u22CF"); - html5Entities.put("cwconint", "\u2232"); - html5Entities.put("cwint", "\u2231"); - html5Entities.put("cylcty", "\u232D"); - html5Entities.put("dagger", "\u2020"); - html5Entities.put("Dagger", "\u2021"); - html5Entities.put("daleth", "\u2138"); - html5Entities.put("darr", "\u2193"); - html5Entities.put("Darr", "\u21A1"); - html5Entities.put("dArr", "\u21D3"); - html5Entities.put("dash", "\u2010"); - html5Entities.put("Dashv", "\u2AE4"); - html5Entities.put("dashv", "\u22A3"); - html5Entities.put("dbkarow", "\u290F"); - html5Entities.put("dblac", "\u02DD"); - html5Entities.put("Dcaron", "\u010E"); - html5Entities.put("dcaron", "\u010F"); - html5Entities.put("Dcy", "\u0414"); - html5Entities.put("dcy", "\u0434"); - html5Entities.put("ddagger", "\u2021"); - html5Entities.put("ddarr", "\u21CA"); - html5Entities.put("DD", "\u2145"); - html5Entities.put("dd", "\u2146"); - html5Entities.put("DDotrahd", "\u2911"); - html5Entities.put("ddotseq", "\u2A77"); - html5Entities.put("deg", "\u00B0"); - html5Entities.put("Del", "\u2207"); - html5Entities.put("Delta", "\u0394"); - html5Entities.put("delta", "\u03B4"); - html5Entities.put("demptyv", "\u29B1"); - html5Entities.put("dfisht", "\u297F"); - html5Entities.put("Dfr", "\uD835\uDD07"); - html5Entities.put("dfr", "\uD835\uDD21"); - html5Entities.put("dHar", "\u2965"); - html5Entities.put("dharl", "\u21C3"); - html5Entities.put("dharr", "\u21C2"); - html5Entities.put("DiacriticalAcute", "\u00B4"); - html5Entities.put("DiacriticalDot", "\u02D9"); - html5Entities.put("DiacriticalDoubleAcute", "\u02DD"); - html5Entities.put("DiacriticalGrave", "\u0060"); - html5Entities.put("DiacriticalTilde", "\u02DC"); - html5Entities.put("diam", "\u22C4"); - html5Entities.put("diamond", "\u22C4"); - html5Entities.put("Diamond", "\u22C4"); - html5Entities.put("diamondsuit", "\u2666"); - html5Entities.put("diams", "\u2666"); - html5Entities.put("die", "\u00A8"); - html5Entities.put("DifferentialD", "\u2146"); - html5Entities.put("digamma", "\u03DD"); - html5Entities.put("disin", "\u22F2"); - html5Entities.put("div", "\u00F7"); - html5Entities.put("divide", "\u00F7"); - html5Entities.put("divideontimes", "\u22C7"); - html5Entities.put("divonx", "\u22C7"); - html5Entities.put("DJcy", "\u0402"); - html5Entities.put("djcy", "\u0452"); - html5Entities.put("dlcorn", "\u231E"); - html5Entities.put("dlcrop", "\u230D"); - html5Entities.put("dollar", "\u0024"); - html5Entities.put("Dopf", "\uD835\uDD3B"); - html5Entities.put("dopf", "\uD835\uDD55"); - html5Entities.put("Dot", "\u00A8"); - html5Entities.put("dot", "\u02D9"); - html5Entities.put("DotDot", "\u20DC"); - html5Entities.put("doteq", "\u2250"); - html5Entities.put("doteqdot", "\u2251"); - html5Entities.put("DotEqual", "\u2250"); - html5Entities.put("dotminus", "\u2238"); - html5Entities.put("dotplus", "\u2214"); - html5Entities.put("dotsquare", "\u22A1"); - html5Entities.put("doublebarwedge", "\u2306"); - html5Entities.put("DoubleContourIntegral", "\u222F"); - html5Entities.put("DoubleDot", "\u00A8"); - html5Entities.put("DoubleDownArrow", "\u21D3"); - html5Entities.put("DoubleLeftArrow", "\u21D0"); - html5Entities.put("DoubleLeftRightArrow", "\u21D4"); - html5Entities.put("DoubleLeftTee", "\u2AE4"); - html5Entities.put("DoubleLongLeftArrow", "\u27F8"); - html5Entities.put("DoubleLongLeftRightArrow", "\u27FA"); - html5Entities.put("DoubleLongRightArrow", "\u27F9"); - html5Entities.put("DoubleRightArrow", "\u21D2"); - html5Entities.put("DoubleRightTee", "\u22A8"); - html5Entities.put("DoubleUpArrow", "\u21D1"); - html5Entities.put("DoubleUpDownArrow", "\u21D5"); - html5Entities.put("DoubleVerticalBar", "\u2225"); - html5Entities.put("DownArrowBar", "\u2913"); - html5Entities.put("downarrow", "\u2193"); - html5Entities.put("DownArrow", "\u2193"); - html5Entities.put("Downarrow", "\u21D3"); - html5Entities.put("DownArrowUpArrow", "\u21F5"); - html5Entities.put("DownBreve", "\u0311"); - html5Entities.put("downdownarrows", "\u21CA"); - html5Entities.put("downharpoonleft", "\u21C3"); - html5Entities.put("downharpoonright", "\u21C2"); - html5Entities.put("DownLeftRightVector", "\u2950"); - html5Entities.put("DownLeftTeeVector", "\u295E"); - html5Entities.put("DownLeftVectorBar", "\u2956"); - html5Entities.put("DownLeftVector", "\u21BD"); - html5Entities.put("DownRightTeeVector", "\u295F"); - html5Entities.put("DownRightVectorBar", "\u2957"); - html5Entities.put("DownRightVector", "\u21C1"); - html5Entities.put("DownTeeArrow", "\u21A7"); - html5Entities.put("DownTee", "\u22A4"); - html5Entities.put("drbkarow", "\u2910"); - html5Entities.put("drcorn", "\u231F"); - html5Entities.put("drcrop", "\u230C"); - html5Entities.put("Dscr", "\uD835\uDC9F"); - html5Entities.put("dscr", "\uD835\uDCB9"); - html5Entities.put("DScy", "\u0405"); - html5Entities.put("dscy", "\u0455"); - html5Entities.put("dsol", "\u29F6"); - html5Entities.put("Dstrok", "\u0110"); - html5Entities.put("dstrok", "\u0111"); - html5Entities.put("dtdot", "\u22F1"); - html5Entities.put("dtri", "\u25BF"); - html5Entities.put("dtrif", "\u25BE"); - html5Entities.put("duarr", "\u21F5"); - html5Entities.put("duhar", "\u296F"); - html5Entities.put("dwangle", "\u29A6"); - html5Entities.put("DZcy", "\u040F"); - html5Entities.put("dzcy", "\u045F"); - html5Entities.put("dzigrarr", "\u27FF"); - html5Entities.put("Eacute", "\u00C9"); - html5Entities.put("eacute", "\u00E9"); - html5Entities.put("easter", "\u2A6E"); - html5Entities.put("Ecaron", "\u011A"); - html5Entities.put("ecaron", "\u011B"); - html5Entities.put("Ecirc", "\u00CA"); - html5Entities.put("ecirc", "\u00EA"); - html5Entities.put("ecir", "\u2256"); - html5Entities.put("ecolon", "\u2255"); - html5Entities.put("Ecy", "\u042D"); - html5Entities.put("ecy", "\u044D"); - html5Entities.put("eDDot", "\u2A77"); - html5Entities.put("Edot", "\u0116"); - html5Entities.put("edot", "\u0117"); - html5Entities.put("eDot", "\u2251"); - html5Entities.put("ee", "\u2147"); - html5Entities.put("efDot", "\u2252"); - html5Entities.put("Efr", "\uD835\uDD08"); - html5Entities.put("efr", "\uD835\uDD22"); - html5Entities.put("eg", "\u2A9A"); - html5Entities.put("Egrave", "\u00C8"); - html5Entities.put("egrave", "\u00E8"); - html5Entities.put("egs", "\u2A96"); - html5Entities.put("egsdot", "\u2A98"); - html5Entities.put("el", "\u2A99"); - html5Entities.put("Element", "\u2208"); - html5Entities.put("elinters", "\u23E7"); - html5Entities.put("ell", "\u2113"); - html5Entities.put("els", "\u2A95"); - html5Entities.put("elsdot", "\u2A97"); - html5Entities.put("Emacr", "\u0112"); - html5Entities.put("emacr", "\u0113"); - html5Entities.put("empty", "\u2205"); - html5Entities.put("emptyset", "\u2205"); - html5Entities.put("EmptySmallSquare", "\u25FB"); - html5Entities.put("emptyv", "\u2205"); - html5Entities.put("EmptyVerySmallSquare", "\u25AB"); - html5Entities.put("emsp13", "\u2004"); - html5Entities.put("emsp14", "\u2005"); - html5Entities.put("emsp", "\u2003"); - html5Entities.put("ENG", "\u014A"); - html5Entities.put("eng", "\u014B"); - html5Entities.put("ensp", "\u2002"); - html5Entities.put("Eogon", "\u0118"); - html5Entities.put("eogon", "\u0119"); - html5Entities.put("Eopf", "\uD835\uDD3C"); - html5Entities.put("eopf", "\uD835\uDD56"); - html5Entities.put("epar", "\u22D5"); - html5Entities.put("eparsl", "\u29E3"); - html5Entities.put("eplus", "\u2A71"); - html5Entities.put("epsi", "\u03B5"); - html5Entities.put("Epsilon", "\u0395"); - html5Entities.put("epsilon", "\u03B5"); - html5Entities.put("epsiv", "\u03F5"); - html5Entities.put("eqcirc", "\u2256"); - html5Entities.put("eqcolon", "\u2255"); - html5Entities.put("eqsim", "\u2242"); - html5Entities.put("eqslantgtr", "\u2A96"); - html5Entities.put("eqslantless", "\u2A95"); - html5Entities.put("Equal", "\u2A75"); - html5Entities.put("equals", "\u003D"); - html5Entities.put("EqualTilde", "\u2242"); - html5Entities.put("equest", "\u225F"); - html5Entities.put("Equilibrium", "\u21CC"); - html5Entities.put("equiv", "\u2261"); - html5Entities.put("equivDD", "\u2A78"); - html5Entities.put("eqvparsl", "\u29E5"); - html5Entities.put("erarr", "\u2971"); - html5Entities.put("erDot", "\u2253"); - html5Entities.put("escr", "\u212F"); - html5Entities.put("Escr", "\u2130"); - html5Entities.put("esdot", "\u2250"); - html5Entities.put("Esim", "\u2A73"); - html5Entities.put("esim", "\u2242"); - html5Entities.put("Eta", "\u0397"); - html5Entities.put("eta", "\u03B7"); - html5Entities.put("ETH", "\u00D0"); - html5Entities.put("eth", "\u00F0"); - html5Entities.put("Euml", "\u00CB"); - html5Entities.put("euml", "\u00EB"); - html5Entities.put("euro", "\u20AC"); - html5Entities.put("excl", "\u0021"); - html5Entities.put("exist", "\u2203"); - html5Entities.put("Exists", "\u2203"); - html5Entities.put("expectation", "\u2130"); - html5Entities.put("exponentiale", "\u2147"); - html5Entities.put("ExponentialE", "\u2147"); - html5Entities.put("fallingdotseq", "\u2252"); - html5Entities.put("Fcy", "\u0424"); - html5Entities.put("fcy", "\u0444"); - html5Entities.put("female", "\u2640"); - html5Entities.put("ffilig", "\uFB03"); - html5Entities.put("fflig", "\uFB00"); - html5Entities.put("ffllig", "\uFB04"); - html5Entities.put("Ffr", "\uD835\uDD09"); - html5Entities.put("ffr", "\uD835\uDD23"); - html5Entities.put("filig", "\uFB01"); - html5Entities.put("FilledSmallSquare", "\u25FC"); - html5Entities.put("FilledVerySmallSquare", "\u25AA"); - html5Entities.put("fjlig", "\u0066\u006A"); - html5Entities.put("flat", "\u266D"); - html5Entities.put("fllig", "\uFB02"); - html5Entities.put("fltns", "\u25B1"); - html5Entities.put("fnof", "\u0192"); - html5Entities.put("Fopf", "\uD835\uDD3D"); - html5Entities.put("fopf", "\uD835\uDD57"); - html5Entities.put("forall", "\u2200"); - html5Entities.put("ForAll", "\u2200"); - html5Entities.put("fork", "\u22D4"); - html5Entities.put("forkv", "\u2AD9"); - html5Entities.put("Fouriertrf", "\u2131"); - html5Entities.put("fpartint", "\u2A0D"); - html5Entities.put("frac12", "\u00BD"); - html5Entities.put("frac13", "\u2153"); - html5Entities.put("frac14", "\u00BC"); - html5Entities.put("frac15", "\u2155"); - html5Entities.put("frac16", "\u2159"); - html5Entities.put("frac18", "\u215B"); - html5Entities.put("frac23", "\u2154"); - html5Entities.put("frac25", "\u2156"); - html5Entities.put("frac34", "\u00BE"); - html5Entities.put("frac35", "\u2157"); - html5Entities.put("frac38", "\u215C"); - html5Entities.put("frac45", "\u2158"); - html5Entities.put("frac56", "\u215A"); - html5Entities.put("frac58", "\u215D"); - html5Entities.put("frac78", "\u215E"); - html5Entities.put("frasl", "\u2044"); - html5Entities.put("frown", "\u2322"); - html5Entities.put("fscr", "\uD835\uDCBB"); - html5Entities.put("Fscr", "\u2131"); - html5Entities.put("gacute", "\u01F5"); - html5Entities.put("Gamma", "\u0393"); - html5Entities.put("gamma", "\u03B3"); - html5Entities.put("Gammad", "\u03DC"); - html5Entities.put("gammad", "\u03DD"); - html5Entities.put("gap", "\u2A86"); - html5Entities.put("Gbreve", "\u011E"); - html5Entities.put("gbreve", "\u011F"); - html5Entities.put("Gcedil", "\u0122"); - html5Entities.put("Gcirc", "\u011C"); - html5Entities.put("gcirc", "\u011D"); - html5Entities.put("Gcy", "\u0413"); - html5Entities.put("gcy", "\u0433"); - html5Entities.put("Gdot", "\u0120"); - html5Entities.put("gdot", "\u0121"); - html5Entities.put("ge", "\u2265"); - html5Entities.put("gE", "\u2267"); - html5Entities.put("gEl", "\u2A8C"); - html5Entities.put("gel", "\u22DB"); - html5Entities.put("geq", "\u2265"); - html5Entities.put("geqq", "\u2267"); - html5Entities.put("geqslant", "\u2A7E"); - html5Entities.put("gescc", "\u2AA9"); - html5Entities.put("ges", "\u2A7E"); - html5Entities.put("gesdot", "\u2A80"); - html5Entities.put("gesdoto", "\u2A82"); - html5Entities.put("gesdotol", "\u2A84"); - html5Entities.put("gesl", "\u22DB\uFE00"); - html5Entities.put("gesles", "\u2A94"); - html5Entities.put("Gfr", "\uD835\uDD0A"); - html5Entities.put("gfr", "\uD835\uDD24"); - html5Entities.put("gg", "\u226B"); - html5Entities.put("Gg", "\u22D9"); - html5Entities.put("ggg", "\u22D9"); - html5Entities.put("gimel", "\u2137"); - html5Entities.put("GJcy", "\u0403"); - html5Entities.put("gjcy", "\u0453"); - html5Entities.put("gla", "\u2AA5"); - html5Entities.put("gl", "\u2277"); - html5Entities.put("glE", "\u2A92"); - html5Entities.put("glj", "\u2AA4"); - html5Entities.put("gnap", "\u2A8A"); - html5Entities.put("gnapprox", "\u2A8A"); - html5Entities.put("gne", "\u2A88"); - html5Entities.put("gnE", "\u2269"); - html5Entities.put("gneq", "\u2A88"); - html5Entities.put("gneqq", "\u2269"); - html5Entities.put("gnsim", "\u22E7"); - html5Entities.put("Gopf", "\uD835\uDD3E"); - html5Entities.put("gopf", "\uD835\uDD58"); - html5Entities.put("grave", "\u0060"); - html5Entities.put("GreaterEqual", "\u2265"); - html5Entities.put("GreaterEqualLess", "\u22DB"); - html5Entities.put("GreaterFullEqual", "\u2267"); - html5Entities.put("GreaterGreater", "\u2AA2"); - html5Entities.put("GreaterLess", "\u2277"); - html5Entities.put("GreaterSlantEqual", "\u2A7E"); - html5Entities.put("GreaterTilde", "\u2273"); - html5Entities.put("Gscr", "\uD835\uDCA2"); - html5Entities.put("gscr", "\u210A"); - html5Entities.put("gsim", "\u2273"); - html5Entities.put("gsime", "\u2A8E"); - html5Entities.put("gsiml", "\u2A90"); - html5Entities.put("gtcc", "\u2AA7"); - html5Entities.put("gtcir", "\u2A7A"); - html5Entities.put("gt", "\u003E"); - html5Entities.put("GT", "\u003E"); - html5Entities.put("Gt", "\u226B"); - html5Entities.put("gtdot", "\u22D7"); - html5Entities.put("gtlPar", "\u2995"); - html5Entities.put("gtquest", "\u2A7C"); - html5Entities.put("gtrapprox", "\u2A86"); - html5Entities.put("gtrarr", "\u2978"); - html5Entities.put("gtrdot", "\u22D7"); - html5Entities.put("gtreqless", "\u22DB"); - html5Entities.put("gtreqqless", "\u2A8C"); - html5Entities.put("gtrless", "\u2277"); - html5Entities.put("gtrsim", "\u2273"); - html5Entities.put("gvertneqq", "\u2269\uFE00"); - html5Entities.put("gvnE", "\u2269\uFE00"); - html5Entities.put("Hacek", "\u02C7"); - html5Entities.put("hairsp", "\u200A"); - html5Entities.put("half", "\u00BD"); - html5Entities.put("hamilt", "\u210B"); - html5Entities.put("HARDcy", "\u042A"); - html5Entities.put("hardcy", "\u044A"); - html5Entities.put("harrcir", "\u2948"); - html5Entities.put("harr", "\u2194"); - html5Entities.put("hArr", "\u21D4"); - html5Entities.put("harrw", "\u21AD"); - html5Entities.put("Hat", "\u005E"); - html5Entities.put("hbar", "\u210F"); - html5Entities.put("Hcirc", "\u0124"); - html5Entities.put("hcirc", "\u0125"); - html5Entities.put("hearts", "\u2665"); - html5Entities.put("heartsuit", "\u2665"); - html5Entities.put("hellip", "\u2026"); - html5Entities.put("hercon", "\u22B9"); - html5Entities.put("hfr", "\uD835\uDD25"); - html5Entities.put("Hfr", "\u210C"); - html5Entities.put("HilbertSpace", "\u210B"); - html5Entities.put("hksearow", "\u2925"); - html5Entities.put("hkswarow", "\u2926"); - html5Entities.put("hoarr", "\u21FF"); - html5Entities.put("homtht", "\u223B"); - html5Entities.put("hookleftarrow", "\u21A9"); - html5Entities.put("hookrightarrow", "\u21AA"); - html5Entities.put("hopf", "\uD835\uDD59"); - html5Entities.put("Hopf", "\u210D"); - html5Entities.put("horbar", "\u2015"); - html5Entities.put("HorizontalLine", "\u2500"); - html5Entities.put("hscr", "\uD835\uDCBD"); - html5Entities.put("Hscr", "\u210B"); - html5Entities.put("hslash", "\u210F"); - html5Entities.put("Hstrok", "\u0126"); - html5Entities.put("hstrok", "\u0127"); - html5Entities.put("HumpDownHump", "\u224E"); - html5Entities.put("HumpEqual", "\u224F"); - html5Entities.put("hybull", "\u2043"); - html5Entities.put("hyphen", "\u2010"); - html5Entities.put("Iacute", "\u00CD"); - html5Entities.put("iacute", "\u00ED"); - html5Entities.put("ic", "\u2063"); - html5Entities.put("Icirc", "\u00CE"); - html5Entities.put("icirc", "\u00EE"); - html5Entities.put("Icy", "\u0418"); - html5Entities.put("icy", "\u0438"); - html5Entities.put("Idot", "\u0130"); - html5Entities.put("IEcy", "\u0415"); - html5Entities.put("iecy", "\u0435"); - html5Entities.put("iexcl", "\u00A1"); - html5Entities.put("iff", "\u21D4"); - html5Entities.put("ifr", "\uD835\uDD26"); - html5Entities.put("Ifr", "\u2111"); - html5Entities.put("Igrave", "\u00CC"); - html5Entities.put("igrave", "\u00EC"); - html5Entities.put("ii", "\u2148"); - html5Entities.put("iiiint", "\u2A0C"); - html5Entities.put("iiint", "\u222D"); - html5Entities.put("iinfin", "\u29DC"); - html5Entities.put("iiota", "\u2129"); - html5Entities.put("IJlig", "\u0132"); - html5Entities.put("ijlig", "\u0133"); - html5Entities.put("Imacr", "\u012A"); - html5Entities.put("imacr", "\u012B"); - html5Entities.put("image", "\u2111"); - html5Entities.put("ImaginaryI", "\u2148"); - html5Entities.put("imagline", "\u2110"); - html5Entities.put("imagpart", "\u2111"); - html5Entities.put("imath", "\u0131"); - html5Entities.put("Im", "\u2111"); - html5Entities.put("imof", "\u22B7"); - html5Entities.put("imped", "\u01B5"); - html5Entities.put("Implies", "\u21D2"); - html5Entities.put("incare", "\u2105"); - html5Entities.put("in", "\u2208"); - html5Entities.put("infin", "\u221E"); - html5Entities.put("infintie", "\u29DD"); - html5Entities.put("inodot", "\u0131"); - html5Entities.put("intcal", "\u22BA"); - html5Entities.put("int", "\u222B"); - html5Entities.put("Int", "\u222C"); - html5Entities.put("integers", "\u2124"); - html5Entities.put("Integral", "\u222B"); - html5Entities.put("intercal", "\u22BA"); - html5Entities.put("Intersection", "\u22C2"); - html5Entities.put("intlarhk", "\u2A17"); - html5Entities.put("intprod", "\u2A3C"); - html5Entities.put("InvisibleComma", "\u2063"); - html5Entities.put("InvisibleTimes", "\u2062"); - html5Entities.put("IOcy", "\u0401"); - html5Entities.put("iocy", "\u0451"); - html5Entities.put("Iogon", "\u012E"); - html5Entities.put("iogon", "\u012F"); - html5Entities.put("Iopf", "\uD835\uDD40"); - html5Entities.put("iopf", "\uD835\uDD5A"); - html5Entities.put("Iota", "\u0399"); - html5Entities.put("iota", "\u03B9"); - html5Entities.put("iprod", "\u2A3C"); - html5Entities.put("iquest", "\u00BF"); - html5Entities.put("iscr", "\uD835\uDCBE"); - html5Entities.put("Iscr", "\u2110"); - html5Entities.put("isin", "\u2208"); - html5Entities.put("isindot", "\u22F5"); - html5Entities.put("isinE", "\u22F9"); - html5Entities.put("isins", "\u22F4"); - html5Entities.put("isinsv", "\u22F3"); - html5Entities.put("isinv", "\u2208"); - html5Entities.put("it", "\u2062"); - html5Entities.put("Itilde", "\u0128"); - html5Entities.put("itilde", "\u0129"); - html5Entities.put("Iukcy", "\u0406"); - html5Entities.put("iukcy", "\u0456"); - html5Entities.put("Iuml", "\u00CF"); - html5Entities.put("iuml", "\u00EF"); - html5Entities.put("Jcirc", "\u0134"); - html5Entities.put("jcirc", "\u0135"); - html5Entities.put("Jcy", "\u0419"); - html5Entities.put("jcy", "\u0439"); - html5Entities.put("Jfr", "\uD835\uDD0D"); - html5Entities.put("jfr", "\uD835\uDD27"); - html5Entities.put("jmath", "\u0237"); - html5Entities.put("Jopf", "\uD835\uDD41"); - html5Entities.put("jopf", "\uD835\uDD5B"); - html5Entities.put("Jscr", "\uD835\uDCA5"); - html5Entities.put("jscr", "\uD835\uDCBF"); - html5Entities.put("Jsercy", "\u0408"); - html5Entities.put("jsercy", "\u0458"); - html5Entities.put("Jukcy", "\u0404"); - html5Entities.put("jukcy", "\u0454"); - html5Entities.put("Kappa", "\u039A"); - html5Entities.put("kappa", "\u03BA"); - html5Entities.put("kappav", "\u03F0"); - html5Entities.put("Kcedil", "\u0136"); - html5Entities.put("kcedil", "\u0137"); - html5Entities.put("Kcy", "\u041A"); - html5Entities.put("kcy", "\u043A"); - html5Entities.put("Kfr", "\uD835\uDD0E"); - html5Entities.put("kfr", "\uD835\uDD28"); - html5Entities.put("kgreen", "\u0138"); - html5Entities.put("KHcy", "\u0425"); - html5Entities.put("khcy", "\u0445"); - html5Entities.put("KJcy", "\u040C"); - html5Entities.put("kjcy", "\u045C"); - html5Entities.put("Kopf", "\uD835\uDD42"); - html5Entities.put("kopf", "\uD835\uDD5C"); - html5Entities.put("Kscr", "\uD835\uDCA6"); - html5Entities.put("kscr", "\uD835\uDCC0"); - html5Entities.put("lAarr", "\u21DA"); - html5Entities.put("Lacute", "\u0139"); - html5Entities.put("lacute", "\u013A"); - html5Entities.put("laemptyv", "\u29B4"); - html5Entities.put("lagran", "\u2112"); - html5Entities.put("Lambda", "\u039B"); - html5Entities.put("lambda", "\u03BB"); - html5Entities.put("lang", "\u27E8"); - html5Entities.put("Lang", "\u27EA"); - html5Entities.put("langd", "\u2991"); - html5Entities.put("langle", "\u27E8"); - html5Entities.put("lap", "\u2A85"); - html5Entities.put("Laplacetrf", "\u2112"); - html5Entities.put("laquo", "\u00AB"); - html5Entities.put("larrb", "\u21E4"); - html5Entities.put("larrbfs", "\u291F"); - html5Entities.put("larr", "\u2190"); - html5Entities.put("Larr", "\u219E"); - html5Entities.put("lArr", "\u21D0"); - html5Entities.put("larrfs", "\u291D"); - html5Entities.put("larrhk", "\u21A9"); - html5Entities.put("larrlp", "\u21AB"); - html5Entities.put("larrpl", "\u2939"); - html5Entities.put("larrsim", "\u2973"); - html5Entities.put("larrtl", "\u21A2"); - html5Entities.put("latail", "\u2919"); - html5Entities.put("lAtail", "\u291B"); - html5Entities.put("lat", "\u2AAB"); - html5Entities.put("late", "\u2AAD"); - html5Entities.put("lates", "\u2AAD\uFE00"); - html5Entities.put("lbarr", "\u290C"); - html5Entities.put("lBarr", "\u290E"); - html5Entities.put("lbbrk", "\u2772"); - html5Entities.put("lbrace", "\u007B"); - html5Entities.put("lbrack", "\u005B"); - html5Entities.put("lbrke", "\u298B"); - html5Entities.put("lbrksld", "\u298F"); - html5Entities.put("lbrkslu", "\u298D"); - html5Entities.put("Lcaron", "\u013D"); - html5Entities.put("lcaron", "\u013E"); - html5Entities.put("Lcedil", "\u013B"); - html5Entities.put("lcedil", "\u013C"); - html5Entities.put("lceil", "\u2308"); - html5Entities.put("lcub", "\u007B"); - html5Entities.put("Lcy", "\u041B"); - html5Entities.put("lcy", "\u043B"); - html5Entities.put("ldca", "\u2936"); - html5Entities.put("ldquo", "\u201C"); - html5Entities.put("ldquor", "\u201E"); - html5Entities.put("ldrdhar", "\u2967"); - html5Entities.put("ldrushar", "\u294B"); - html5Entities.put("ldsh", "\u21B2"); - html5Entities.put("le", "\u2264"); - html5Entities.put("lE", "\u2266"); - html5Entities.put("LeftAngleBracket", "\u27E8"); - html5Entities.put("LeftArrowBar", "\u21E4"); - html5Entities.put("leftarrow", "\u2190"); - html5Entities.put("LeftArrow", "\u2190"); - html5Entities.put("Leftarrow", "\u21D0"); - html5Entities.put("LeftArrowRightArrow", "\u21C6"); - html5Entities.put("leftarrowtail", "\u21A2"); - html5Entities.put("LeftCeiling", "\u2308"); - html5Entities.put("LeftDoubleBracket", "\u27E6"); - html5Entities.put("LeftDownTeeVector", "\u2961"); - html5Entities.put("LeftDownVectorBar", "\u2959"); - html5Entities.put("LeftDownVector", "\u21C3"); - html5Entities.put("LeftFloor", "\u230A"); - html5Entities.put("leftharpoondown", "\u21BD"); - html5Entities.put("leftharpoonup", "\u21BC"); - html5Entities.put("leftleftarrows", "\u21C7"); - html5Entities.put("leftrightarrow", "\u2194"); - html5Entities.put("LeftRightArrow", "\u2194"); - html5Entities.put("Leftrightarrow", "\u21D4"); - html5Entities.put("leftrightarrows", "\u21C6"); - html5Entities.put("leftrightharpoons", "\u21CB"); - html5Entities.put("leftrightsquigarrow", "\u21AD"); - html5Entities.put("LeftRightVector", "\u294E"); - html5Entities.put("LeftTeeArrow", "\u21A4"); - html5Entities.put("LeftTee", "\u22A3"); - html5Entities.put("LeftTeeVector", "\u295A"); - html5Entities.put("leftthreetimes", "\u22CB"); - html5Entities.put("LeftTriangleBar", "\u29CF"); - html5Entities.put("LeftTriangle", "\u22B2"); - html5Entities.put("LeftTriangleEqual", "\u22B4"); - html5Entities.put("LeftUpDownVector", "\u2951"); - html5Entities.put("LeftUpTeeVector", "\u2960"); - html5Entities.put("LeftUpVectorBar", "\u2958"); - html5Entities.put("LeftUpVector", "\u21BF"); - html5Entities.put("LeftVectorBar", "\u2952"); - html5Entities.put("LeftVector", "\u21BC"); - html5Entities.put("lEg", "\u2A8B"); - html5Entities.put("leg", "\u22DA"); - html5Entities.put("leq", "\u2264"); - html5Entities.put("leqq", "\u2266"); - html5Entities.put("leqslant", "\u2A7D"); - html5Entities.put("lescc", "\u2AA8"); - html5Entities.put("les", "\u2A7D"); - html5Entities.put("lesdot", "\u2A7F"); - html5Entities.put("lesdoto", "\u2A81"); - html5Entities.put("lesdotor", "\u2A83"); - html5Entities.put("lesg", "\u22DA\uFE00"); - html5Entities.put("lesges", "\u2A93"); - html5Entities.put("lessapprox", "\u2A85"); - html5Entities.put("lessdot", "\u22D6"); - html5Entities.put("lesseqgtr", "\u22DA"); - html5Entities.put("lesseqqgtr", "\u2A8B"); - html5Entities.put("LessEqualGreater", "\u22DA"); - html5Entities.put("LessFullEqual", "\u2266"); - html5Entities.put("LessGreater", "\u2276"); - html5Entities.put("lessgtr", "\u2276"); - html5Entities.put("LessLess", "\u2AA1"); - html5Entities.put("lesssim", "\u2272"); - html5Entities.put("LessSlantEqual", "\u2A7D"); - html5Entities.put("LessTilde", "\u2272"); - html5Entities.put("lfisht", "\u297C"); - html5Entities.put("lfloor", "\u230A"); - html5Entities.put("Lfr", "\uD835\uDD0F"); - html5Entities.put("lfr", "\uD835\uDD29"); - html5Entities.put("lg", "\u2276"); - html5Entities.put("lgE", "\u2A91"); - html5Entities.put("lHar", "\u2962"); - html5Entities.put("lhard", "\u21BD"); - html5Entities.put("lharu", "\u21BC"); - html5Entities.put("lharul", "\u296A"); - html5Entities.put("lhblk", "\u2584"); - html5Entities.put("LJcy", "\u0409"); - html5Entities.put("ljcy", "\u0459"); - html5Entities.put("llarr", "\u21C7"); - html5Entities.put("ll", "\u226A"); - html5Entities.put("Ll", "\u22D8"); - html5Entities.put("llcorner", "\u231E"); - html5Entities.put("Lleftarrow", "\u21DA"); - html5Entities.put("llhard", "\u296B"); - html5Entities.put("lltri", "\u25FA"); - html5Entities.put("Lmidot", "\u013F"); - html5Entities.put("lmidot", "\u0140"); - html5Entities.put("lmoustache", "\u23B0"); - html5Entities.put("lmoust", "\u23B0"); - html5Entities.put("lnap", "\u2A89"); - html5Entities.put("lnapprox", "\u2A89"); - html5Entities.put("lne", "\u2A87"); - html5Entities.put("lnE", "\u2268"); - html5Entities.put("lneq", "\u2A87"); - html5Entities.put("lneqq", "\u2268"); - html5Entities.put("lnsim", "\u22E6"); - html5Entities.put("loang", "\u27EC"); - html5Entities.put("loarr", "\u21FD"); - html5Entities.put("lobrk", "\u27E6"); - html5Entities.put("longleftarrow", "\u27F5"); - html5Entities.put("LongLeftArrow", "\u27F5"); - html5Entities.put("Longleftarrow", "\u27F8"); - html5Entities.put("longleftrightarrow", "\u27F7"); - html5Entities.put("LongLeftRightArrow", "\u27F7"); - html5Entities.put("Longleftrightarrow", "\u27FA"); - html5Entities.put("longmapsto", "\u27FC"); - html5Entities.put("longrightarrow", "\u27F6"); - html5Entities.put("LongRightArrow", "\u27F6"); - html5Entities.put("Longrightarrow", "\u27F9"); - html5Entities.put("looparrowleft", "\u21AB"); - html5Entities.put("looparrowright", "\u21AC"); - html5Entities.put("lopar", "\u2985"); - html5Entities.put("Lopf", "\uD835\uDD43"); - html5Entities.put("lopf", "\uD835\uDD5D"); - html5Entities.put("loplus", "\u2A2D"); - html5Entities.put("lotimes", "\u2A34"); - html5Entities.put("lowast", "\u2217"); - html5Entities.put("lowbar", "\u005F"); - html5Entities.put("LowerLeftArrow", "\u2199"); - html5Entities.put("LowerRightArrow", "\u2198"); - html5Entities.put("loz", "\u25CA"); - html5Entities.put("lozenge", "\u25CA"); - html5Entities.put("lozf", "\u29EB"); - html5Entities.put("lpar", "\u0028"); - html5Entities.put("lparlt", "\u2993"); - html5Entities.put("lrarr", "\u21C6"); - html5Entities.put("lrcorner", "\u231F"); - html5Entities.put("lrhar", "\u21CB"); - html5Entities.put("lrhard", "\u296D"); - html5Entities.put("lrm", "\u200E"); - html5Entities.put("lrtri", "\u22BF"); - html5Entities.put("lsaquo", "\u2039"); - html5Entities.put("lscr", "\uD835\uDCC1"); - html5Entities.put("Lscr", "\u2112"); - html5Entities.put("lsh", "\u21B0"); - html5Entities.put("Lsh", "\u21B0"); - html5Entities.put("lsim", "\u2272"); - html5Entities.put("lsime", "\u2A8D"); - html5Entities.put("lsimg", "\u2A8F"); - html5Entities.put("lsqb", "\u005B"); - html5Entities.put("lsquo", "\u2018"); - html5Entities.put("lsquor", "\u201A"); - html5Entities.put("Lstrok", "\u0141"); - html5Entities.put("lstrok", "\u0142"); - html5Entities.put("ltcc", "\u2AA6"); - html5Entities.put("ltcir", "\u2A79"); - html5Entities.put("lt", "\u003C"); - html5Entities.put("LT", "\u003C"); - html5Entities.put("Lt", "\u226A"); - html5Entities.put("ltdot", "\u22D6"); - html5Entities.put("lthree", "\u22CB"); - html5Entities.put("ltimes", "\u22C9"); - html5Entities.put("ltlarr", "\u2976"); - html5Entities.put("ltquest", "\u2A7B"); - html5Entities.put("ltri", "\u25C3"); - html5Entities.put("ltrie", "\u22B4"); - html5Entities.put("ltrif", "\u25C2"); - html5Entities.put("ltrPar", "\u2996"); - html5Entities.put("lurdshar", "\u294A"); - html5Entities.put("luruhar", "\u2966"); - html5Entities.put("lvertneqq", "\u2268\uFE00"); - html5Entities.put("lvnE", "\u2268\uFE00"); - html5Entities.put("macr", "\u00AF"); - html5Entities.put("male", "\u2642"); - html5Entities.put("malt", "\u2720"); - html5Entities.put("maltese", "\u2720"); - html5Entities.put("Map", "\u2905"); - html5Entities.put("map", "\u21A6"); - html5Entities.put("mapsto", "\u21A6"); - html5Entities.put("mapstodown", "\u21A7"); - html5Entities.put("mapstoleft", "\u21A4"); - html5Entities.put("mapstoup", "\u21A5"); - html5Entities.put("marker", "\u25AE"); - html5Entities.put("mcomma", "\u2A29"); - html5Entities.put("Mcy", "\u041C"); - html5Entities.put("mcy", "\u043C"); - html5Entities.put("mdash", "\u2014"); - html5Entities.put("mDDot", "\u223A"); - html5Entities.put("measuredangle", "\u2221"); - html5Entities.put("MediumSpace", "\u205F"); - html5Entities.put("Mellintrf", "\u2133"); - html5Entities.put("Mfr", "\uD835\uDD10"); - html5Entities.put("mfr", "\uD835\uDD2A"); - html5Entities.put("mho", "\u2127"); - html5Entities.put("micro", "\u00B5"); - html5Entities.put("midast", "\u002A"); - html5Entities.put("midcir", "\u2AF0"); - html5Entities.put("mid", "\u2223"); - html5Entities.put("middot", "\u00B7"); - html5Entities.put("minusb", "\u229F"); - html5Entities.put("minus", "\u2212"); - html5Entities.put("minusd", "\u2238"); - html5Entities.put("minusdu", "\u2A2A"); - html5Entities.put("MinusPlus", "\u2213"); - html5Entities.put("mlcp", "\u2ADB"); - html5Entities.put("mldr", "\u2026"); - html5Entities.put("mnplus", "\u2213"); - html5Entities.put("models", "\u22A7"); - html5Entities.put("Mopf", "\uD835\uDD44"); - html5Entities.put("mopf", "\uD835\uDD5E"); - html5Entities.put("mp", "\u2213"); - html5Entities.put("mscr", "\uD835\uDCC2"); - html5Entities.put("Mscr", "\u2133"); - html5Entities.put("mstpos", "\u223E"); - html5Entities.put("Mu", "\u039C"); - html5Entities.put("mu", "\u03BC"); - html5Entities.put("multimap", "\u22B8"); - html5Entities.put("mumap", "\u22B8"); - html5Entities.put("nabla", "\u2207"); - html5Entities.put("Nacute", "\u0143"); - html5Entities.put("nacute", "\u0144"); - html5Entities.put("nang", "\u2220\u20D2"); - html5Entities.put("nap", "\u2249"); - html5Entities.put("napE", "\u2A70\u0338"); - html5Entities.put("napid", "\u224B\u0338"); - html5Entities.put("napos", "\u0149"); - html5Entities.put("napprox", "\u2249"); - html5Entities.put("natural", "\u266E"); - html5Entities.put("naturals", "\u2115"); - html5Entities.put("natur", "\u266E"); - html5Entities.put("nbsp", "\u00A0"); - html5Entities.put("nbump", "\u224E\u0338"); - html5Entities.put("nbumpe", "\u224F\u0338"); - html5Entities.put("ncap", "\u2A43"); - html5Entities.put("Ncaron", "\u0147"); - html5Entities.put("ncaron", "\u0148"); - html5Entities.put("Ncedil", "\u0145"); - html5Entities.put("ncedil", "\u0146"); - html5Entities.put("ncong", "\u2247"); - html5Entities.put("ncongdot", "\u2A6D\u0338"); - html5Entities.put("ncup", "\u2A42"); - html5Entities.put("Ncy", "\u041D"); - html5Entities.put("ncy", "\u043D"); - html5Entities.put("ndash", "\u2013"); - html5Entities.put("nearhk", "\u2924"); - html5Entities.put("nearr", "\u2197"); - html5Entities.put("neArr", "\u21D7"); - html5Entities.put("nearrow", "\u2197"); - html5Entities.put("ne", "\u2260"); - html5Entities.put("nedot", "\u2250\u0338"); - html5Entities.put("NegativeMediumSpace", "\u200B"); - html5Entities.put("NegativeThickSpace", "\u200B"); - html5Entities.put("NegativeThinSpace", "\u200B"); - html5Entities.put("NegativeVeryThinSpace", "\u200B"); - html5Entities.put("nequiv", "\u2262"); - html5Entities.put("nesear", "\u2928"); - html5Entities.put("nesim", "\u2242\u0338"); - html5Entities.put("NestedGreaterGreater", "\u226B"); - html5Entities.put("NestedLessLess", "\u226A"); - html5Entities.put("NewLine", "\n"); - html5Entities.put("nexist", "\u2204"); - html5Entities.put("nexists", "\u2204"); - html5Entities.put("Nfr", "\uD835\uDD11"); - html5Entities.put("nfr", "\uD835\uDD2B"); - html5Entities.put("ngE", "\u2267\u0338"); - html5Entities.put("nge", "\u2271"); - html5Entities.put("ngeq", "\u2271"); - html5Entities.put("ngeqq", "\u2267\u0338"); - html5Entities.put("ngeqslant", "\u2A7E\u0338"); - html5Entities.put("nges", "\u2A7E\u0338"); - html5Entities.put("nGg", "\u22D9\u0338"); - html5Entities.put("ngsim", "\u2275"); - html5Entities.put("nGt", "\u226B\u20D2"); - html5Entities.put("ngt", "\u226F"); - html5Entities.put("ngtr", "\u226F"); - html5Entities.put("nGtv", "\u226B\u0338"); - html5Entities.put("nharr", "\u21AE"); - html5Entities.put("nhArr", "\u21CE"); - html5Entities.put("nhpar", "\u2AF2"); - html5Entities.put("ni", "\u220B"); - html5Entities.put("nis", "\u22FC"); - html5Entities.put("nisd", "\u22FA"); - html5Entities.put("niv", "\u220B"); - html5Entities.put("NJcy", "\u040A"); - html5Entities.put("njcy", "\u045A"); - html5Entities.put("nlarr", "\u219A"); - html5Entities.put("nlArr", "\u21CD"); - html5Entities.put("nldr", "\u2025"); - html5Entities.put("nlE", "\u2266\u0338"); - html5Entities.put("nle", "\u2270"); - html5Entities.put("nleftarrow", "\u219A"); - html5Entities.put("nLeftarrow", "\u21CD"); - html5Entities.put("nleftrightarrow", "\u21AE"); - html5Entities.put("nLeftrightarrow", "\u21CE"); - html5Entities.put("nleq", "\u2270"); - html5Entities.put("nleqq", "\u2266\u0338"); - html5Entities.put("nleqslant", "\u2A7D\u0338"); - html5Entities.put("nles", "\u2A7D\u0338"); - html5Entities.put("nless", "\u226E"); - html5Entities.put("nLl", "\u22D8\u0338"); - html5Entities.put("nlsim", "\u2274"); - html5Entities.put("nLt", "\u226A\u20D2"); - html5Entities.put("nlt", "\u226E"); - html5Entities.put("nltri", "\u22EA"); - html5Entities.put("nltrie", "\u22EC"); - html5Entities.put("nLtv", "\u226A\u0338"); - html5Entities.put("nmid", "\u2224"); - html5Entities.put("NoBreak", "\u2060"); - html5Entities.put("NonBreakingSpace", "\u00A0"); - html5Entities.put("nopf", "\uD835\uDD5F"); - html5Entities.put("Nopf", "\u2115"); - html5Entities.put("Not", "\u2AEC"); - html5Entities.put("not", "\u00AC"); - html5Entities.put("NotCongruent", "\u2262"); - html5Entities.put("NotCupCap", "\u226D"); - html5Entities.put("NotDoubleVerticalBar", "\u2226"); - html5Entities.put("NotElement", "\u2209"); - html5Entities.put("NotEqual", "\u2260"); - html5Entities.put("NotEqualTilde", "\u2242\u0338"); - html5Entities.put("NotExists", "\u2204"); - html5Entities.put("NotGreater", "\u226F"); - html5Entities.put("NotGreaterEqual", "\u2271"); - html5Entities.put("NotGreaterFullEqual", "\u2267\u0338"); - html5Entities.put("NotGreaterGreater", "\u226B\u0338"); - html5Entities.put("NotGreaterLess", "\u2279"); - html5Entities.put("NotGreaterSlantEqual", "\u2A7E\u0338"); - html5Entities.put("NotGreaterTilde", "\u2275"); - html5Entities.put("NotHumpDownHump", "\u224E\u0338"); - html5Entities.put("NotHumpEqual", "\u224F\u0338"); - html5Entities.put("notin", "\u2209"); - html5Entities.put("notindot", "\u22F5\u0338"); - html5Entities.put("notinE", "\u22F9\u0338"); - html5Entities.put("notinva", "\u2209"); - html5Entities.put("notinvb", "\u22F7"); - html5Entities.put("notinvc", "\u22F6"); - html5Entities.put("NotLeftTriangleBar", "\u29CF\u0338"); - html5Entities.put("NotLeftTriangle", "\u22EA"); - html5Entities.put("NotLeftTriangleEqual", "\u22EC"); - html5Entities.put("NotLess", "\u226E"); - html5Entities.put("NotLessEqual", "\u2270"); - html5Entities.put("NotLessGreater", "\u2278"); - html5Entities.put("NotLessLess", "\u226A\u0338"); - html5Entities.put("NotLessSlantEqual", "\u2A7D\u0338"); - html5Entities.put("NotLessTilde", "\u2274"); - html5Entities.put("NotNestedGreaterGreater", "\u2AA2\u0338"); - html5Entities.put("NotNestedLessLess", "\u2AA1\u0338"); - html5Entities.put("notni", "\u220C"); - html5Entities.put("notniva", "\u220C"); - html5Entities.put("notnivb", "\u22FE"); - html5Entities.put("notnivc", "\u22FD"); - html5Entities.put("NotPrecedes", "\u2280"); - html5Entities.put("NotPrecedesEqual", "\u2AAF\u0338"); - html5Entities.put("NotPrecedesSlantEqual", "\u22E0"); - html5Entities.put("NotReverseElement", "\u220C"); - html5Entities.put("NotRightTriangleBar", "\u29D0\u0338"); - html5Entities.put("NotRightTriangle", "\u22EB"); - html5Entities.put("NotRightTriangleEqual", "\u22ED"); - html5Entities.put("NotSquareSubset", "\u228F\u0338"); - html5Entities.put("NotSquareSubsetEqual", "\u22E2"); - html5Entities.put("NotSquareSuperset", "\u2290\u0338"); - html5Entities.put("NotSquareSupersetEqual", "\u22E3"); - html5Entities.put("NotSubset", "\u2282\u20D2"); - html5Entities.put("NotSubsetEqual", "\u2288"); - html5Entities.put("NotSucceeds", "\u2281"); - html5Entities.put("NotSucceedsEqual", "\u2AB0\u0338"); - html5Entities.put("NotSucceedsSlantEqual", "\u22E1"); - html5Entities.put("NotSucceedsTilde", "\u227F\u0338"); - html5Entities.put("NotSuperset", "\u2283\u20D2"); - html5Entities.put("NotSupersetEqual", "\u2289"); - html5Entities.put("NotTilde", "\u2241"); - html5Entities.put("NotTildeEqual", "\u2244"); - html5Entities.put("NotTildeFullEqual", "\u2247"); - html5Entities.put("NotTildeTilde", "\u2249"); - html5Entities.put("NotVerticalBar", "\u2224"); - html5Entities.put("nparallel", "\u2226"); - html5Entities.put("npar", "\u2226"); - html5Entities.put("nparsl", "\u2AFD\u20E5"); - html5Entities.put("npart", "\u2202\u0338"); - html5Entities.put("npolint", "\u2A14"); - html5Entities.put("npr", "\u2280"); - html5Entities.put("nprcue", "\u22E0"); - html5Entities.put("nprec", "\u2280"); - html5Entities.put("npreceq", "\u2AAF\u0338"); - html5Entities.put("npre", "\u2AAF\u0338"); - html5Entities.put("nrarrc", "\u2933\u0338"); - html5Entities.put("nrarr", "\u219B"); - html5Entities.put("nrArr", "\u21CF"); - html5Entities.put("nrarrw", "\u219D\u0338"); - html5Entities.put("nrightarrow", "\u219B"); - html5Entities.put("nRightarrow", "\u21CF"); - html5Entities.put("nrtri", "\u22EB"); - html5Entities.put("nrtrie", "\u22ED"); - html5Entities.put("nsc", "\u2281"); - html5Entities.put("nsccue", "\u22E1"); - html5Entities.put("nsce", "\u2AB0\u0338"); - html5Entities.put("Nscr", "\uD835\uDCA9"); - html5Entities.put("nscr", "\uD835\uDCC3"); - html5Entities.put("nshortmid", "\u2224"); - html5Entities.put("nshortparallel", "\u2226"); - html5Entities.put("nsim", "\u2241"); - html5Entities.put("nsime", "\u2244"); - html5Entities.put("nsimeq", "\u2244"); - html5Entities.put("nsmid", "\u2224"); - html5Entities.put("nspar", "\u2226"); - html5Entities.put("nsqsube", "\u22E2"); - html5Entities.put("nsqsupe", "\u22E3"); - html5Entities.put("nsub", "\u2284"); - html5Entities.put("nsubE", "\u2AC5\u0338"); - html5Entities.put("nsube", "\u2288"); - html5Entities.put("nsubset", "\u2282\u20D2"); - html5Entities.put("nsubseteq", "\u2288"); - html5Entities.put("nsubseteqq", "\u2AC5\u0338"); - html5Entities.put("nsucc", "\u2281"); - html5Entities.put("nsucceq", "\u2AB0\u0338"); - html5Entities.put("nsup", "\u2285"); - html5Entities.put("nsupE", "\u2AC6\u0338"); - html5Entities.put("nsupe", "\u2289"); - html5Entities.put("nsupset", "\u2283\u20D2"); - html5Entities.put("nsupseteq", "\u2289"); - html5Entities.put("nsupseteqq", "\u2AC6\u0338"); - html5Entities.put("ntgl", "\u2279"); - html5Entities.put("Ntilde", "\u00D1"); - html5Entities.put("ntilde", "\u00F1"); - html5Entities.put("ntlg", "\u2278"); - html5Entities.put("ntriangleleft", "\u22EA"); - html5Entities.put("ntrianglelefteq", "\u22EC"); - html5Entities.put("ntriangleright", "\u22EB"); - html5Entities.put("ntrianglerighteq", "\u22ED"); - html5Entities.put("Nu", "\u039D"); - html5Entities.put("nu", "\u03BD"); - html5Entities.put("num", "\u0023"); - html5Entities.put("numero", "\u2116"); - html5Entities.put("numsp", "\u2007"); - html5Entities.put("nvap", "\u224D\u20D2"); - html5Entities.put("nvdash", "\u22AC"); - html5Entities.put("nvDash", "\u22AD"); - html5Entities.put("nVdash", "\u22AE"); - html5Entities.put("nVDash", "\u22AF"); - html5Entities.put("nvge", "\u2265\u20D2"); - html5Entities.put("nvgt", "\u003E\u20D2"); - html5Entities.put("nvHarr", "\u2904"); - html5Entities.put("nvinfin", "\u29DE"); - html5Entities.put("nvlArr", "\u2902"); - html5Entities.put("nvle", "\u2264\u20D2"); - html5Entities.put("nvlt", "\u003C\u20D2"); - html5Entities.put("nvltrie", "\u22B4\u20D2"); - html5Entities.put("nvrArr", "\u2903"); - html5Entities.put("nvrtrie", "\u22B5\u20D2"); - html5Entities.put("nvsim", "\u223C\u20D2"); - html5Entities.put("nwarhk", "\u2923"); - html5Entities.put("nwarr", "\u2196"); - html5Entities.put("nwArr", "\u21D6"); - html5Entities.put("nwarrow", "\u2196"); - html5Entities.put("nwnear", "\u2927"); - html5Entities.put("Oacute", "\u00D3"); - html5Entities.put("oacute", "\u00F3"); - html5Entities.put("oast", "\u229B"); - html5Entities.put("Ocirc", "\u00D4"); - html5Entities.put("ocirc", "\u00F4"); - html5Entities.put("ocir", "\u229A"); - html5Entities.put("Ocy", "\u041E"); - html5Entities.put("ocy", "\u043E"); - html5Entities.put("odash", "\u229D"); - html5Entities.put("Odblac", "\u0150"); - html5Entities.put("odblac", "\u0151"); - html5Entities.put("odiv", "\u2A38"); - html5Entities.put("odot", "\u2299"); - html5Entities.put("odsold", "\u29BC"); - html5Entities.put("OElig", "\u0152"); - html5Entities.put("oelig", "\u0153"); - html5Entities.put("ofcir", "\u29BF"); - html5Entities.put("Ofr", "\uD835\uDD12"); - html5Entities.put("ofr", "\uD835\uDD2C"); - html5Entities.put("ogon", "\u02DB"); - html5Entities.put("Ograve", "\u00D2"); - html5Entities.put("ograve", "\u00F2"); - html5Entities.put("ogt", "\u29C1"); - html5Entities.put("ohbar", "\u29B5"); - html5Entities.put("ohm", "\u03A9"); - html5Entities.put("oint", "\u222E"); - html5Entities.put("olarr", "\u21BA"); - html5Entities.put("olcir", "\u29BE"); - html5Entities.put("olcross", "\u29BB"); - html5Entities.put("oline", "\u203E"); - html5Entities.put("olt", "\u29C0"); - html5Entities.put("Omacr", "\u014C"); - html5Entities.put("omacr", "\u014D"); - html5Entities.put("Omega", "\u03A9"); - html5Entities.put("omega", "\u03C9"); - html5Entities.put("Omicron", "\u039F"); - html5Entities.put("omicron", "\u03BF"); - html5Entities.put("omid", "\u29B6"); - html5Entities.put("ominus", "\u2296"); - html5Entities.put("Oopf", "\uD835\uDD46"); - html5Entities.put("oopf", "\uD835\uDD60"); - html5Entities.put("opar", "\u29B7"); - html5Entities.put("OpenCurlyDoubleQuote", "\u201C"); - html5Entities.put("OpenCurlyQuote", "\u2018"); - html5Entities.put("operp", "\u29B9"); - html5Entities.put("oplus", "\u2295"); - html5Entities.put("orarr", "\u21BB"); - html5Entities.put("Or", "\u2A54"); - html5Entities.put("or", "\u2228"); - html5Entities.put("ord", "\u2A5D"); - html5Entities.put("order", "\u2134"); - html5Entities.put("orderof", "\u2134"); - html5Entities.put("ordf", "\u00AA"); - html5Entities.put("ordm", "\u00BA"); - html5Entities.put("origof", "\u22B6"); - html5Entities.put("oror", "\u2A56"); - html5Entities.put("orslope", "\u2A57"); - html5Entities.put("orv", "\u2A5B"); - html5Entities.put("oS", "\u24C8"); - html5Entities.put("Oscr", "\uD835\uDCAA"); - html5Entities.put("oscr", "\u2134"); - html5Entities.put("Oslash", "\u00D8"); - html5Entities.put("oslash", "\u00F8"); - html5Entities.put("osol", "\u2298"); - html5Entities.put("Otilde", "\u00D5"); - html5Entities.put("otilde", "\u00F5"); - html5Entities.put("otimesas", "\u2A36"); - html5Entities.put("Otimes", "\u2A37"); - html5Entities.put("otimes", "\u2297"); - html5Entities.put("Ouml", "\u00D6"); - html5Entities.put("ouml", "\u00F6"); - html5Entities.put("ovbar", "\u233D"); - html5Entities.put("OverBar", "\u203E"); - html5Entities.put("OverBrace", "\u23DE"); - html5Entities.put("OverBracket", "\u23B4"); - html5Entities.put("OverParenthesis", "\u23DC"); - html5Entities.put("para", "\u00B6"); - html5Entities.put("parallel", "\u2225"); - html5Entities.put("par", "\u2225"); - html5Entities.put("parsim", "\u2AF3"); - html5Entities.put("parsl", "\u2AFD"); - html5Entities.put("part", "\u2202"); - html5Entities.put("PartialD", "\u2202"); - html5Entities.put("Pcy", "\u041F"); - html5Entities.put("pcy", "\u043F"); - html5Entities.put("percnt", "\u0025"); - html5Entities.put("period", "\u002E"); - html5Entities.put("permil", "\u2030"); - html5Entities.put("perp", "\u22A5"); - html5Entities.put("pertenk", "\u2031"); - html5Entities.put("Pfr", "\uD835\uDD13"); - html5Entities.put("pfr", "\uD835\uDD2D"); - html5Entities.put("Phi", "\u03A6"); - html5Entities.put("phi", "\u03C6"); - html5Entities.put("phiv", "\u03D5"); - html5Entities.put("phmmat", "\u2133"); - html5Entities.put("phone", "\u260E"); - html5Entities.put("Pi", "\u03A0"); - html5Entities.put("pi", "\u03C0"); - html5Entities.put("pitchfork", "\u22D4"); - html5Entities.put("piv", "\u03D6"); - html5Entities.put("planck", "\u210F"); - html5Entities.put("planckh", "\u210E"); - html5Entities.put("plankv", "\u210F"); - html5Entities.put("plusacir", "\u2A23"); - html5Entities.put("plusb", "\u229E"); - html5Entities.put("pluscir", "\u2A22"); - html5Entities.put("plus", "\u002B"); - html5Entities.put("plusdo", "\u2214"); - html5Entities.put("plusdu", "\u2A25"); - html5Entities.put("pluse", "\u2A72"); - html5Entities.put("PlusMinus", "\u00B1"); - html5Entities.put("plusmn", "\u00B1"); - html5Entities.put("plussim", "\u2A26"); - html5Entities.put("plustwo", "\u2A27"); - html5Entities.put("pm", "\u00B1"); - html5Entities.put("Poincareplane", "\u210C"); - html5Entities.put("pointint", "\u2A15"); - html5Entities.put("popf", "\uD835\uDD61"); - html5Entities.put("Popf", "\u2119"); - html5Entities.put("pound", "\u00A3"); - html5Entities.put("prap", "\u2AB7"); - html5Entities.put("Pr", "\u2ABB"); - html5Entities.put("pr", "\u227A"); - html5Entities.put("prcue", "\u227C"); - html5Entities.put("precapprox", "\u2AB7"); - html5Entities.put("prec", "\u227A"); - html5Entities.put("preccurlyeq", "\u227C"); - html5Entities.put("Precedes", "\u227A"); - html5Entities.put("PrecedesEqual", "\u2AAF"); - html5Entities.put("PrecedesSlantEqual", "\u227C"); - html5Entities.put("PrecedesTilde", "\u227E"); - html5Entities.put("preceq", "\u2AAF"); - html5Entities.put("precnapprox", "\u2AB9"); - html5Entities.put("precneqq", "\u2AB5"); - html5Entities.put("precnsim", "\u22E8"); - html5Entities.put("pre", "\u2AAF"); - html5Entities.put("prE", "\u2AB3"); - html5Entities.put("precsim", "\u227E"); - html5Entities.put("prime", "\u2032"); - html5Entities.put("Prime", "\u2033"); - html5Entities.put("primes", "\u2119"); - html5Entities.put("prnap", "\u2AB9"); - html5Entities.put("prnE", "\u2AB5"); - html5Entities.put("prnsim", "\u22E8"); - html5Entities.put("prod", "\u220F"); - html5Entities.put("Product", "\u220F"); - html5Entities.put("profalar", "\u232E"); - html5Entities.put("profline", "\u2312"); - html5Entities.put("profsurf", "\u2313"); - html5Entities.put("prop", "\u221D"); - html5Entities.put("Proportional", "\u221D"); - html5Entities.put("Proportion", "\u2237"); - html5Entities.put("propto", "\u221D"); - html5Entities.put("prsim", "\u227E"); - html5Entities.put("prurel", "\u22B0"); - html5Entities.put("Pscr", "\uD835\uDCAB"); - html5Entities.put("pscr", "\uD835\uDCC5"); - html5Entities.put("Psi", "\u03A8"); - html5Entities.put("psi", "\u03C8"); - html5Entities.put("puncsp", "\u2008"); - html5Entities.put("Qfr", "\uD835\uDD14"); - html5Entities.put("qfr", "\uD835\uDD2E"); - html5Entities.put("qint", "\u2A0C"); - html5Entities.put("qopf", "\uD835\uDD62"); - html5Entities.put("Qopf", "\u211A"); - html5Entities.put("qprime", "\u2057"); - html5Entities.put("Qscr", "\uD835\uDCAC"); - html5Entities.put("qscr", "\uD835\uDCC6"); - html5Entities.put("quaternions", "\u210D"); - html5Entities.put("quatint", "\u2A16"); - html5Entities.put("quest", "\u003F"); - html5Entities.put("questeq", "\u225F"); - html5Entities.put("quot", "\""); - html5Entities.put("QUOT", "\""); - html5Entities.put("rAarr", "\u21DB"); - html5Entities.put("race", "\u223D\u0331"); - html5Entities.put("Racute", "\u0154"); - html5Entities.put("racute", "\u0155"); - html5Entities.put("radic", "\u221A"); - html5Entities.put("raemptyv", "\u29B3"); - html5Entities.put("rang", "\u27E9"); - html5Entities.put("Rang", "\u27EB"); - html5Entities.put("rangd", "\u2992"); - html5Entities.put("range", "\u29A5"); - html5Entities.put("rangle", "\u27E9"); - html5Entities.put("raquo", "\u00BB"); - html5Entities.put("rarrap", "\u2975"); - html5Entities.put("rarrb", "\u21E5"); - html5Entities.put("rarrbfs", "\u2920"); - html5Entities.put("rarrc", "\u2933"); - html5Entities.put("rarr", "\u2192"); - html5Entities.put("Rarr", "\u21A0"); - html5Entities.put("rArr", "\u21D2"); - html5Entities.put("rarrfs", "\u291E"); - html5Entities.put("rarrhk", "\u21AA"); - html5Entities.put("rarrlp", "\u21AC"); - html5Entities.put("rarrpl", "\u2945"); - html5Entities.put("rarrsim", "\u2974"); - html5Entities.put("Rarrtl", "\u2916"); - html5Entities.put("rarrtl", "\u21A3"); - html5Entities.put("rarrw", "\u219D"); - html5Entities.put("ratail", "\u291A"); - html5Entities.put("rAtail", "\u291C"); - html5Entities.put("ratio", "\u2236"); - html5Entities.put("rationals", "\u211A"); - html5Entities.put("rbarr", "\u290D"); - html5Entities.put("rBarr", "\u290F"); - html5Entities.put("RBarr", "\u2910"); - html5Entities.put("rbbrk", "\u2773"); - html5Entities.put("rbrace", "\u007D"); - html5Entities.put("rbrack", "\u005D"); - html5Entities.put("rbrke", "\u298C"); - html5Entities.put("rbrksld", "\u298E"); - html5Entities.put("rbrkslu", "\u2990"); - html5Entities.put("Rcaron", "\u0158"); - html5Entities.put("rcaron", "\u0159"); - html5Entities.put("Rcedil", "\u0156"); - html5Entities.put("rcedil", "\u0157"); - html5Entities.put("rceil", "\u2309"); - html5Entities.put("rcub", "\u007D"); - html5Entities.put("Rcy", "\u0420"); - html5Entities.put("rcy", "\u0440"); - html5Entities.put("rdca", "\u2937"); - html5Entities.put("rdldhar", "\u2969"); - html5Entities.put("rdquo", "\u201D"); - html5Entities.put("rdquor", "\u201D"); - html5Entities.put("rdsh", "\u21B3"); - html5Entities.put("real", "\u211C"); - html5Entities.put("realine", "\u211B"); - html5Entities.put("realpart", "\u211C"); - html5Entities.put("reals", "\u211D"); - html5Entities.put("Re", "\u211C"); - html5Entities.put("rect", "\u25AD"); - html5Entities.put("reg", "\u00AE"); - html5Entities.put("REG", "\u00AE"); - html5Entities.put("ReverseElement", "\u220B"); - html5Entities.put("ReverseEquilibrium", "\u21CB"); - html5Entities.put("ReverseUpEquilibrium", "\u296F"); - html5Entities.put("rfisht", "\u297D"); - html5Entities.put("rfloor", "\u230B"); - html5Entities.put("rfr", "\uD835\uDD2F"); - html5Entities.put("Rfr", "\u211C"); - html5Entities.put("rHar", "\u2964"); - html5Entities.put("rhard", "\u21C1"); - html5Entities.put("rharu", "\u21C0"); - html5Entities.put("rharul", "\u296C"); - html5Entities.put("Rho", "\u03A1"); - html5Entities.put("rho", "\u03C1"); - html5Entities.put("rhov", "\u03F1"); - html5Entities.put("RightAngleBracket", "\u27E9"); - html5Entities.put("RightArrowBar", "\u21E5"); - html5Entities.put("rightarrow", "\u2192"); - html5Entities.put("RightArrow", "\u2192"); - html5Entities.put("Rightarrow", "\u21D2"); - html5Entities.put("RightArrowLeftArrow", "\u21C4"); - html5Entities.put("rightarrowtail", "\u21A3"); - html5Entities.put("RightCeiling", "\u2309"); - html5Entities.put("RightDoubleBracket", "\u27E7"); - html5Entities.put("RightDownTeeVector", "\u295D"); - html5Entities.put("RightDownVectorBar", "\u2955"); - html5Entities.put("RightDownVector", "\u21C2"); - html5Entities.put("RightFloor", "\u230B"); - html5Entities.put("rightharpoondown", "\u21C1"); - html5Entities.put("rightharpoonup", "\u21C0"); - html5Entities.put("rightleftarrows", "\u21C4"); - html5Entities.put("rightleftharpoons", "\u21CC"); - html5Entities.put("rightrightarrows", "\u21C9"); - html5Entities.put("rightsquigarrow", "\u219D"); - html5Entities.put("RightTeeArrow", "\u21A6"); - html5Entities.put("RightTee", "\u22A2"); - html5Entities.put("RightTeeVector", "\u295B"); - html5Entities.put("rightthreetimes", "\u22CC"); - html5Entities.put("RightTriangleBar", "\u29D0"); - html5Entities.put("RightTriangle", "\u22B3"); - html5Entities.put("RightTriangleEqual", "\u22B5"); - html5Entities.put("RightUpDownVector", "\u294F"); - html5Entities.put("RightUpTeeVector", "\u295C"); - html5Entities.put("RightUpVectorBar", "\u2954"); - html5Entities.put("RightUpVector", "\u21BE"); - html5Entities.put("RightVectorBar", "\u2953"); - html5Entities.put("RightVector", "\u21C0"); - html5Entities.put("ring", "\u02DA"); - html5Entities.put("risingdotseq", "\u2253"); - html5Entities.put("rlarr", "\u21C4"); - html5Entities.put("rlhar", "\u21CC"); - html5Entities.put("rlm", "\u200F"); - html5Entities.put("rmoustache", "\u23B1"); - html5Entities.put("rmoust", "\u23B1"); - html5Entities.put("rnmid", "\u2AEE"); - html5Entities.put("roang", "\u27ED"); - html5Entities.put("roarr", "\u21FE"); - html5Entities.put("robrk", "\u27E7"); - html5Entities.put("ropar", "\u2986"); - html5Entities.put("ropf", "\uD835\uDD63"); - html5Entities.put("Ropf", "\u211D"); - html5Entities.put("roplus", "\u2A2E"); - html5Entities.put("rotimes", "\u2A35"); - html5Entities.put("RoundImplies", "\u2970"); - html5Entities.put("rpar", "\u0029"); - html5Entities.put("rpargt", "\u2994"); - html5Entities.put("rppolint", "\u2A12"); - html5Entities.put("rrarr", "\u21C9"); - html5Entities.put("Rrightarrow", "\u21DB"); - html5Entities.put("rsaquo", "\u203A"); - html5Entities.put("rscr", "\uD835\uDCC7"); - html5Entities.put("Rscr", "\u211B"); - html5Entities.put("rsh", "\u21B1"); - html5Entities.put("Rsh", "\u21B1"); - html5Entities.put("rsqb", "\u005D"); - html5Entities.put("rsquo", "\u2019"); - html5Entities.put("rsquor", "\u2019"); - html5Entities.put("rthree", "\u22CC"); - html5Entities.put("rtimes", "\u22CA"); - html5Entities.put("rtri", "\u25B9"); - html5Entities.put("rtrie", "\u22B5"); - html5Entities.put("rtrif", "\u25B8"); - html5Entities.put("rtriltri", "\u29CE"); - html5Entities.put("RuleDelayed", "\u29F4"); - html5Entities.put("ruluhar", "\u2968"); - html5Entities.put("rx", "\u211E"); - html5Entities.put("Sacute", "\u015A"); - html5Entities.put("sacute", "\u015B"); - html5Entities.put("sbquo", "\u201A"); - html5Entities.put("scap", "\u2AB8"); - html5Entities.put("Scaron", "\u0160"); - html5Entities.put("scaron", "\u0161"); - html5Entities.put("Sc", "\u2ABC"); - html5Entities.put("sc", "\u227B"); - html5Entities.put("sccue", "\u227D"); - html5Entities.put("sce", "\u2AB0"); - html5Entities.put("scE", "\u2AB4"); - html5Entities.put("Scedil", "\u015E"); - html5Entities.put("scedil", "\u015F"); - html5Entities.put("Scirc", "\u015C"); - html5Entities.put("scirc", "\u015D"); - html5Entities.put("scnap", "\u2ABA"); - html5Entities.put("scnE", "\u2AB6"); - html5Entities.put("scnsim", "\u22E9"); - html5Entities.put("scpolint", "\u2A13"); - html5Entities.put("scsim", "\u227F"); - html5Entities.put("Scy", "\u0421"); - html5Entities.put("scy", "\u0441"); - html5Entities.put("sdotb", "\u22A1"); - html5Entities.put("sdot", "\u22C5"); - html5Entities.put("sdote", "\u2A66"); - html5Entities.put("searhk", "\u2925"); - html5Entities.put("searr", "\u2198"); - html5Entities.put("seArr", "\u21D8"); - html5Entities.put("searrow", "\u2198"); - html5Entities.put("sect", "\u00A7"); - html5Entities.put("semi", "\u003B"); - html5Entities.put("seswar", "\u2929"); - html5Entities.put("setminus", "\u2216"); - html5Entities.put("setmn", "\u2216"); - html5Entities.put("sext", "\u2736"); - html5Entities.put("Sfr", "\uD835\uDD16"); - html5Entities.put("sfr", "\uD835\uDD30"); - html5Entities.put("sfrown", "\u2322"); - html5Entities.put("sharp", "\u266F"); - html5Entities.put("SHCHcy", "\u0429"); - html5Entities.put("shchcy", "\u0449"); - html5Entities.put("SHcy", "\u0428"); - html5Entities.put("shcy", "\u0448"); - html5Entities.put("ShortDownArrow", "\u2193"); - html5Entities.put("ShortLeftArrow", "\u2190"); - html5Entities.put("shortmid", "\u2223"); - html5Entities.put("shortparallel", "\u2225"); - html5Entities.put("ShortRightArrow", "\u2192"); - html5Entities.put("ShortUpArrow", "\u2191"); - html5Entities.put("shy", "\u00AD"); - html5Entities.put("Sigma", "\u03A3"); - html5Entities.put("sigma", "\u03C3"); - html5Entities.put("sigmaf", "\u03C2"); - html5Entities.put("sigmav", "\u03C2"); - html5Entities.put("sim", "\u223C"); - html5Entities.put("simdot", "\u2A6A"); - html5Entities.put("sime", "\u2243"); - html5Entities.put("simeq", "\u2243"); - html5Entities.put("simg", "\u2A9E"); - html5Entities.put("simgE", "\u2AA0"); - html5Entities.put("siml", "\u2A9D"); - html5Entities.put("simlE", "\u2A9F"); - html5Entities.put("simne", "\u2246"); - html5Entities.put("simplus", "\u2A24"); - html5Entities.put("simrarr", "\u2972"); - html5Entities.put("slarr", "\u2190"); - html5Entities.put("SmallCircle", "\u2218"); - html5Entities.put("smallsetminus", "\u2216"); - html5Entities.put("smashp", "\u2A33"); - html5Entities.put("smeparsl", "\u29E4"); - html5Entities.put("smid", "\u2223"); - html5Entities.put("smile", "\u2323"); - html5Entities.put("smt", "\u2AAA"); - html5Entities.put("smte", "\u2AAC"); - html5Entities.put("smtes", "\u2AAC\uFE00"); - html5Entities.put("SOFTcy", "\u042C"); - html5Entities.put("softcy", "\u044C"); - html5Entities.put("solbar", "\u233F"); - html5Entities.put("solb", "\u29C4"); - html5Entities.put("sol", "\u002F"); - html5Entities.put("Sopf", "\uD835\uDD4A"); - html5Entities.put("sopf", "\uD835\uDD64"); - html5Entities.put("spades", "\u2660"); - html5Entities.put("spadesuit", "\u2660"); - html5Entities.put("spar", "\u2225"); - html5Entities.put("sqcap", "\u2293"); - html5Entities.put("sqcaps", "\u2293\uFE00"); - html5Entities.put("sqcup", "\u2294"); - html5Entities.put("sqcups", "\u2294\uFE00"); - html5Entities.put("Sqrt", "\u221A"); - html5Entities.put("sqsub", "\u228F"); - html5Entities.put("sqsube", "\u2291"); - html5Entities.put("sqsubset", "\u228F"); - html5Entities.put("sqsubseteq", "\u2291"); - html5Entities.put("sqsup", "\u2290"); - html5Entities.put("sqsupe", "\u2292"); - html5Entities.put("sqsupset", "\u2290"); - html5Entities.put("sqsupseteq", "\u2292"); - html5Entities.put("square", "\u25A1"); - html5Entities.put("Square", "\u25A1"); - html5Entities.put("SquareIntersection", "\u2293"); - html5Entities.put("SquareSubset", "\u228F"); - html5Entities.put("SquareSubsetEqual", "\u2291"); - html5Entities.put("SquareSuperset", "\u2290"); - html5Entities.put("SquareSupersetEqual", "\u2292"); - html5Entities.put("SquareUnion", "\u2294"); - html5Entities.put("squarf", "\u25AA"); - html5Entities.put("squ", "\u25A1"); - html5Entities.put("squf", "\u25AA"); - html5Entities.put("srarr", "\u2192"); - html5Entities.put("Sscr", "\uD835\uDCAE"); - html5Entities.put("sscr", "\uD835\uDCC8"); - html5Entities.put("ssetmn", "\u2216"); - html5Entities.put("ssmile", "\u2323"); - html5Entities.put("sstarf", "\u22C6"); - html5Entities.put("Star", "\u22C6"); - html5Entities.put("star", "\u2606"); - html5Entities.put("starf", "\u2605"); - html5Entities.put("straightepsilon", "\u03F5"); - html5Entities.put("straightphi", "\u03D5"); - html5Entities.put("strns", "\u00AF"); - html5Entities.put("sub", "\u2282"); - html5Entities.put("Sub", "\u22D0"); - html5Entities.put("subdot", "\u2ABD"); - html5Entities.put("subE", "\u2AC5"); - html5Entities.put("sube", "\u2286"); - html5Entities.put("subedot", "\u2AC3"); - html5Entities.put("submult", "\u2AC1"); - html5Entities.put("subnE", "\u2ACB"); - html5Entities.put("subne", "\u228A"); - html5Entities.put("subplus", "\u2ABF"); - html5Entities.put("subrarr", "\u2979"); - html5Entities.put("subset", "\u2282"); - html5Entities.put("Subset", "\u22D0"); - html5Entities.put("subseteq", "\u2286"); - html5Entities.put("subseteqq", "\u2AC5"); - html5Entities.put("SubsetEqual", "\u2286"); - html5Entities.put("subsetneq", "\u228A"); - html5Entities.put("subsetneqq", "\u2ACB"); - html5Entities.put("subsim", "\u2AC7"); - html5Entities.put("subsub", "\u2AD5"); - html5Entities.put("subsup", "\u2AD3"); - html5Entities.put("succapprox", "\u2AB8"); - html5Entities.put("succ", "\u227B"); - html5Entities.put("succcurlyeq", "\u227D"); - html5Entities.put("Succeeds", "\u227B"); - html5Entities.put("SucceedsEqual", "\u2AB0"); - html5Entities.put("SucceedsSlantEqual", "\u227D"); - html5Entities.put("SucceedsTilde", "\u227F"); - html5Entities.put("succeq", "\u2AB0"); - html5Entities.put("succnapprox", "\u2ABA"); - html5Entities.put("succneqq", "\u2AB6"); - html5Entities.put("succnsim", "\u22E9"); - html5Entities.put("succsim", "\u227F"); - html5Entities.put("SuchThat", "\u220B"); - html5Entities.put("sum", "\u2211"); - html5Entities.put("Sum", "\u2211"); - html5Entities.put("sung", "\u266A"); - html5Entities.put("sup1", "\u00B9"); - html5Entities.put("sup2", "\u00B2"); - html5Entities.put("sup3", "\u00B3"); - html5Entities.put("sup", "\u2283"); - html5Entities.put("Sup", "\u22D1"); - html5Entities.put("supdot", "\u2ABE"); - html5Entities.put("supdsub", "\u2AD8"); - html5Entities.put("supE", "\u2AC6"); - html5Entities.put("supe", "\u2287"); - html5Entities.put("supedot", "\u2AC4"); - html5Entities.put("Superset", "\u2283"); - html5Entities.put("SupersetEqual", "\u2287"); - html5Entities.put("suphsol", "\u27C9"); - html5Entities.put("suphsub", "\u2AD7"); - html5Entities.put("suplarr", "\u297B"); - html5Entities.put("supmult", "\u2AC2"); - html5Entities.put("supnE", "\u2ACC"); - html5Entities.put("supne", "\u228B"); - html5Entities.put("supplus", "\u2AC0"); - html5Entities.put("supset", "\u2283"); - html5Entities.put("Supset", "\u22D1"); - html5Entities.put("supseteq", "\u2287"); - html5Entities.put("supseteqq", "\u2AC6"); - html5Entities.put("supsetneq", "\u228B"); - html5Entities.put("supsetneqq", "\u2ACC"); - html5Entities.put("supsim", "\u2AC8"); - html5Entities.put("supsub", "\u2AD4"); - html5Entities.put("supsup", "\u2AD6"); - html5Entities.put("swarhk", "\u2926"); - html5Entities.put("swarr", "\u2199"); - html5Entities.put("swArr", "\u21D9"); - html5Entities.put("swarrow", "\u2199"); - html5Entities.put("swnwar", "\u292A"); - html5Entities.put("szlig", "\u00DF"); - html5Entities.put("Tab", "\u0009"); - html5Entities.put("target", "\u2316"); - html5Entities.put("Tau", "\u03A4"); - html5Entities.put("tau", "\u03C4"); - html5Entities.put("tbrk", "\u23B4"); - html5Entities.put("Tcaron", "\u0164"); - html5Entities.put("tcaron", "\u0165"); - html5Entities.put("Tcedil", "\u0162"); - html5Entities.put("tcedil", "\u0163"); - html5Entities.put("Tcy", "\u0422"); - html5Entities.put("tcy", "\u0442"); - html5Entities.put("tdot", "\u20DB"); - html5Entities.put("telrec", "\u2315"); - html5Entities.put("Tfr", "\uD835\uDD17"); - html5Entities.put("tfr", "\uD835\uDD31"); - html5Entities.put("there4", "\u2234"); - html5Entities.put("therefore", "\u2234"); - html5Entities.put("Therefore", "\u2234"); - html5Entities.put("Theta", "\u0398"); - html5Entities.put("theta", "\u03B8"); - html5Entities.put("thetasym", "\u03D1"); - html5Entities.put("thetav", "\u03D1"); - html5Entities.put("thickapprox", "\u2248"); - html5Entities.put("thicksim", "\u223C"); - html5Entities.put("ThickSpace", "\u205F\u200A"); - html5Entities.put("ThinSpace", "\u2009"); - html5Entities.put("thinsp", "\u2009"); - html5Entities.put("thkap", "\u2248"); - html5Entities.put("thksim", "\u223C"); - html5Entities.put("THORN", "\u00DE"); - html5Entities.put("thorn", "\u00FE"); - html5Entities.put("tilde", "\u02DC"); - html5Entities.put("Tilde", "\u223C"); - html5Entities.put("TildeEqual", "\u2243"); - html5Entities.put("TildeFullEqual", "\u2245"); - html5Entities.put("TildeTilde", "\u2248"); - html5Entities.put("timesbar", "\u2A31"); - html5Entities.put("timesb", "\u22A0"); - html5Entities.put("times", "\u00D7"); - html5Entities.put("timesd", "\u2A30"); - html5Entities.put("tint", "\u222D"); - html5Entities.put("toea", "\u2928"); - html5Entities.put("topbot", "\u2336"); - html5Entities.put("topcir", "\u2AF1"); - html5Entities.put("top", "\u22A4"); - html5Entities.put("Topf", "\uD835\uDD4B"); - html5Entities.put("topf", "\uD835\uDD65"); - html5Entities.put("topfork", "\u2ADA"); - html5Entities.put("tosa", "\u2929"); - html5Entities.put("tprime", "\u2034"); - html5Entities.put("trade", "\u2122"); - html5Entities.put("TRADE", "\u2122"); - html5Entities.put("triangle", "\u25B5"); - html5Entities.put("triangledown", "\u25BF"); - html5Entities.put("triangleleft", "\u25C3"); - html5Entities.put("trianglelefteq", "\u22B4"); - html5Entities.put("triangleq", "\u225C"); - html5Entities.put("triangleright", "\u25B9"); - html5Entities.put("trianglerighteq", "\u22B5"); - html5Entities.put("tridot", "\u25EC"); - html5Entities.put("trie", "\u225C"); - html5Entities.put("triminus", "\u2A3A"); - html5Entities.put("TripleDot", "\u20DB"); - html5Entities.put("triplus", "\u2A39"); - html5Entities.put("trisb", "\u29CD"); - html5Entities.put("tritime", "\u2A3B"); - html5Entities.put("trpezium", "\u23E2"); - html5Entities.put("Tscr", "\uD835\uDCAF"); - html5Entities.put("tscr", "\uD835\uDCC9"); - html5Entities.put("TScy", "\u0426"); - html5Entities.put("tscy", "\u0446"); - html5Entities.put("TSHcy", "\u040B"); - html5Entities.put("tshcy", "\u045B"); - html5Entities.put("Tstrok", "\u0166"); - html5Entities.put("tstrok", "\u0167"); - html5Entities.put("twixt", "\u226C"); - html5Entities.put("twoheadleftarrow", "\u219E"); - html5Entities.put("twoheadrightarrow", "\u21A0"); - html5Entities.put("Uacute", "\u00DA"); - html5Entities.put("uacute", "\u00FA"); - html5Entities.put("uarr", "\u2191"); - html5Entities.put("Uarr", "\u219F"); - html5Entities.put("uArr", "\u21D1"); - html5Entities.put("Uarrocir", "\u2949"); - html5Entities.put("Ubrcy", "\u040E"); - html5Entities.put("ubrcy", "\u045E"); - html5Entities.put("Ubreve", "\u016C"); - html5Entities.put("ubreve", "\u016D"); - html5Entities.put("Ucirc", "\u00DB"); - html5Entities.put("ucirc", "\u00FB"); - html5Entities.put("Ucy", "\u0423"); - html5Entities.put("ucy", "\u0443"); - html5Entities.put("udarr", "\u21C5"); - html5Entities.put("Udblac", "\u0170"); - html5Entities.put("udblac", "\u0171"); - html5Entities.put("udhar", "\u296E"); - html5Entities.put("ufisht", "\u297E"); - html5Entities.put("Ufr", "\uD835\uDD18"); - html5Entities.put("ufr", "\uD835\uDD32"); - html5Entities.put("Ugrave", "\u00D9"); - html5Entities.put("ugrave", "\u00F9"); - html5Entities.put("uHar", "\u2963"); - html5Entities.put("uharl", "\u21BF"); - html5Entities.put("uharr", "\u21BE"); - html5Entities.put("uhblk", "\u2580"); - html5Entities.put("ulcorn", "\u231C"); - html5Entities.put("ulcorner", "\u231C"); - html5Entities.put("ulcrop", "\u230F"); - html5Entities.put("ultri", "\u25F8"); - html5Entities.put("Umacr", "\u016A"); - html5Entities.put("umacr", "\u016B"); - html5Entities.put("uml", "\u00A8"); - html5Entities.put("UnderBar", "\u005F"); - html5Entities.put("UnderBrace", "\u23DF"); - html5Entities.put("UnderBracket", "\u23B5"); - html5Entities.put("UnderParenthesis", "\u23DD"); - html5Entities.put("Union", "\u22C3"); - html5Entities.put("UnionPlus", "\u228E"); - html5Entities.put("Uogon", "\u0172"); - html5Entities.put("uogon", "\u0173"); - html5Entities.put("Uopf", "\uD835\uDD4C"); - html5Entities.put("uopf", "\uD835\uDD66"); - html5Entities.put("UpArrowBar", "\u2912"); - html5Entities.put("uparrow", "\u2191"); - html5Entities.put("UpArrow", "\u2191"); - html5Entities.put("Uparrow", "\u21D1"); - html5Entities.put("UpArrowDownArrow", "\u21C5"); - html5Entities.put("updownarrow", "\u2195"); - html5Entities.put("UpDownArrow", "\u2195"); - html5Entities.put("Updownarrow", "\u21D5"); - html5Entities.put("UpEquilibrium", "\u296E"); - html5Entities.put("upharpoonleft", "\u21BF"); - html5Entities.put("upharpoonright", "\u21BE"); - html5Entities.put("uplus", "\u228E"); - html5Entities.put("UpperLeftArrow", "\u2196"); - html5Entities.put("UpperRightArrow", "\u2197"); - html5Entities.put("upsi", "\u03C5"); - html5Entities.put("Upsi", "\u03D2"); - html5Entities.put("upsih", "\u03D2"); - html5Entities.put("Upsilon", "\u03A5"); - html5Entities.put("upsilon", "\u03C5"); - html5Entities.put("UpTeeArrow", "\u21A5"); - html5Entities.put("UpTee", "\u22A5"); - html5Entities.put("upuparrows", "\u21C8"); - html5Entities.put("urcorn", "\u231D"); - html5Entities.put("urcorner", "\u231D"); - html5Entities.put("urcrop", "\u230E"); - html5Entities.put("Uring", "\u016E"); - html5Entities.put("uring", "\u016F"); - html5Entities.put("urtri", "\u25F9"); - html5Entities.put("Uscr", "\uD835\uDCB0"); - html5Entities.put("uscr", "\uD835\uDCCA"); - html5Entities.put("utdot", "\u22F0"); - html5Entities.put("Utilde", "\u0168"); - html5Entities.put("utilde", "\u0169"); - html5Entities.put("utri", "\u25B5"); - html5Entities.put("utrif", "\u25B4"); - html5Entities.put("uuarr", "\u21C8"); - html5Entities.put("Uuml", "\u00DC"); - html5Entities.put("uuml", "\u00FC"); - html5Entities.put("uwangle", "\u29A7"); - html5Entities.put("vangrt", "\u299C"); - html5Entities.put("varepsilon", "\u03F5"); - html5Entities.put("varkappa", "\u03F0"); - html5Entities.put("varnothing", "\u2205"); - html5Entities.put("varphi", "\u03D5"); - html5Entities.put("varpi", "\u03D6"); - html5Entities.put("varpropto", "\u221D"); - html5Entities.put("varr", "\u2195"); - html5Entities.put("vArr", "\u21D5"); - html5Entities.put("varrho", "\u03F1"); - html5Entities.put("varsigma", "\u03C2"); - html5Entities.put("varsubsetneq", "\u228A\uFE00"); - html5Entities.put("varsubsetneqq", "\u2ACB\uFE00"); - html5Entities.put("varsupsetneq", "\u228B\uFE00"); - html5Entities.put("varsupsetneqq", "\u2ACC\uFE00"); - html5Entities.put("vartheta", "\u03D1"); - html5Entities.put("vartriangleleft", "\u22B2"); - html5Entities.put("vartriangleright", "\u22B3"); - html5Entities.put("vBar", "\u2AE8"); - html5Entities.put("Vbar", "\u2AEB"); - html5Entities.put("vBarv", "\u2AE9"); - html5Entities.put("Vcy", "\u0412"); - html5Entities.put("vcy", "\u0432"); - html5Entities.put("vdash", "\u22A2"); - html5Entities.put("vDash", "\u22A8"); - html5Entities.put("Vdash", "\u22A9"); - html5Entities.put("VDash", "\u22AB"); - html5Entities.put("Vdashl", "\u2AE6"); - html5Entities.put("veebar", "\u22BB"); - html5Entities.put("vee", "\u2228"); - html5Entities.put("Vee", "\u22C1"); - html5Entities.put("veeeq", "\u225A"); - html5Entities.put("vellip", "\u22EE"); - html5Entities.put("verbar", "\u007C"); - html5Entities.put("Verbar", "\u2016"); - html5Entities.put("vert", "\u007C"); - html5Entities.put("Vert", "\u2016"); - html5Entities.put("VerticalBar", "\u2223"); - html5Entities.put("VerticalLine", "\u007C"); - html5Entities.put("VerticalSeparator", "\u2758"); - html5Entities.put("VerticalTilde", "\u2240"); - html5Entities.put("VeryThinSpace", "\u200A"); - html5Entities.put("Vfr", "\uD835\uDD19"); - html5Entities.put("vfr", "\uD835\uDD33"); - html5Entities.put("vltri", "\u22B2"); - html5Entities.put("vnsub", "\u2282\u20D2"); - html5Entities.put("vnsup", "\u2283\u20D2"); - html5Entities.put("Vopf", "\uD835\uDD4D"); - html5Entities.put("vopf", "\uD835\uDD67"); - html5Entities.put("vprop", "\u221D"); - html5Entities.put("vrtri", "\u22B3"); - html5Entities.put("Vscr", "\uD835\uDCB1"); - html5Entities.put("vscr", "\uD835\uDCCB"); - html5Entities.put("vsubnE", "\u2ACB\uFE00"); - html5Entities.put("vsubne", "\u228A\uFE00"); - html5Entities.put("vsupnE", "\u2ACC\uFE00"); - html5Entities.put("vsupne", "\u228B\uFE00"); - html5Entities.put("Vvdash", "\u22AA"); - html5Entities.put("vzigzag", "\u299A"); - html5Entities.put("Wcirc", "\u0174"); - html5Entities.put("wcirc", "\u0175"); - html5Entities.put("wedbar", "\u2A5F"); - html5Entities.put("wedge", "\u2227"); - html5Entities.put("Wedge", "\u22C0"); - html5Entities.put("wedgeq", "\u2259"); - html5Entities.put("weierp", "\u2118"); - html5Entities.put("Wfr", "\uD835\uDD1A"); - html5Entities.put("wfr", "\uD835\uDD34"); - html5Entities.put("Wopf", "\uD835\uDD4E"); - html5Entities.put("wopf", "\uD835\uDD68"); - html5Entities.put("wp", "\u2118"); - html5Entities.put("wr", "\u2240"); - html5Entities.put("wreath", "\u2240"); - html5Entities.put("Wscr", "\uD835\uDCB2"); - html5Entities.put("wscr", "\uD835\uDCCC"); - html5Entities.put("xcap", "\u22C2"); - html5Entities.put("xcirc", "\u25EF"); - html5Entities.put("xcup", "\u22C3"); - html5Entities.put("xdtri", "\u25BD"); - html5Entities.put("Xfr", "\uD835\uDD1B"); - html5Entities.put("xfr", "\uD835\uDD35"); - html5Entities.put("xharr", "\u27F7"); - html5Entities.put("xhArr", "\u27FA"); - html5Entities.put("Xi", "\u039E"); - html5Entities.put("xi", "\u03BE"); - html5Entities.put("xlarr", "\u27F5"); - html5Entities.put("xlArr", "\u27F8"); - html5Entities.put("xmap", "\u27FC"); - html5Entities.put("xnis", "\u22FB"); - html5Entities.put("xodot", "\u2A00"); - html5Entities.put("Xopf", "\uD835\uDD4F"); - html5Entities.put("xopf", "\uD835\uDD69"); - html5Entities.put("xoplus", "\u2A01"); - html5Entities.put("xotime", "\u2A02"); - html5Entities.put("xrarr", "\u27F6"); - html5Entities.put("xrArr", "\u27F9"); - html5Entities.put("Xscr", "\uD835\uDCB3"); - html5Entities.put("xscr", "\uD835\uDCCD"); - html5Entities.put("xsqcup", "\u2A06"); - html5Entities.put("xuplus", "\u2A04"); - html5Entities.put("xutri", "\u25B3"); - html5Entities.put("xvee", "\u22C1"); - html5Entities.put("xwedge", "\u22C0"); - html5Entities.put("Yacute", "\u00DD"); - html5Entities.put("yacute", "\u00FD"); - html5Entities.put("YAcy", "\u042F"); - html5Entities.put("yacy", "\u044F"); - html5Entities.put("Ycirc", "\u0176"); - html5Entities.put("ycirc", "\u0177"); - html5Entities.put("Ycy", "\u042B"); - html5Entities.put("ycy", "\u044B"); - html5Entities.put("yen", "\u00A5"); - html5Entities.put("Yfr", "\uD835\uDD1C"); - html5Entities.put("yfr", "\uD835\uDD36"); - html5Entities.put("YIcy", "\u0407"); - html5Entities.put("yicy", "\u0457"); - html5Entities.put("Yopf", "\uD835\uDD50"); - html5Entities.put("yopf", "\uD835\uDD6A"); - html5Entities.put("Yscr", "\uD835\uDCB4"); - html5Entities.put("yscr", "\uD835\uDCCE"); - html5Entities.put("YUcy", "\u042E"); - html5Entities.put("yucy", "\u044E"); - html5Entities.put("yuml", "\u00FF"); - html5Entities.put("Yuml", "\u0178"); - html5Entities.put("Zacute", "\u0179"); - html5Entities.put("zacute", "\u017A"); - html5Entities.put("Zcaron", "\u017D"); - html5Entities.put("zcaron", "\u017E"); - html5Entities.put("Zcy", "\u0417"); - html5Entities.put("zcy", "\u0437"); - html5Entities.put("Zdot", "\u017B"); - html5Entities.put("zdot", "\u017C"); - html5Entities.put("zeetrf", "\u2128"); - html5Entities.put("ZeroWidthSpace", "\u200B"); - html5Entities.put("Zeta", "\u0396"); - html5Entities.put("zeta", "\u03B6"); - html5Entities.put("zfr", "\uD835\uDD37"); - html5Entities.put("Zfr", "\u2128"); - html5Entities.put("ZHcy", "\u0416"); - html5Entities.put("zhcy", "\u0436"); - html5Entities.put("zigrarr", "\u21DD"); - html5Entities.put("zopf", "\uD835\uDD6B"); - html5Entities.put("Zopf", "\u2124"); - html5Entities.put("Zscr", "\uD835\uDCB5"); - html5Entities.put("zscr", "\uD835\uDCCF"); - html5Entities.put("zwj", "\u200D"); - html5Entities.put("zwnj", "\u200C"); - } - - public static boolean isValid(String name) { - return html5Entities.containsKey(name); - } - - public static boolean isValid(int code) { - // See https://www.w3.org/TR/html52/syntax.html#character-references - return Character.isDefined(code) - && (!Character.isISOControl(code) || Character.isSpaceChar(code)) - && (code < 0xd800 || code > 0xdfff); - } - - public static String getValue(String name) { - return html5Entities.get(name); - } -} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/Entity.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/Entity.java new file mode 100644 index 00000000000..577bc674b59 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/Entity.java @@ -0,0 +1,2206 @@ +/* + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.tools.javac.api; + +import java.util.HashMap; + +import com.sun.source.doctree.EntityTree; +import com.sun.tools.javac.util.StringUtils; + +/** + * Table of entities defined in HTML 5.2. + * + * <p> Derived from the + * <a href="https://www.w3.org/TR/html52/syntax.html#named-character-references">Named character references</a> + * section of the HTML 5.2 specification. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.</b></p> + */ +class Entity { + + private static final HashMap<String,String> entities = new HashMap<>(); + + static { + put("Aacute", '\u00C1'); + put("aacute", '\u00E1'); + put("Abreve", '\u0102'); + put("abreve", '\u0103'); + put("ac", '\u223E'); + put("acd", '\u223F'); + put("acE", '\u223E', '\u0333'); + put("Acirc", '\u00C2'); + put("acirc", '\u00E2'); + put("acute", '\u00B4'); + put("Acy", '\u0410'); + put("acy", '\u0430'); + put("AElig", '\u00C6'); + put("aelig", '\u00E6'); + put("af", '\u2061'); + put("Afr", '\uD835', '\uDD04'); + put("afr", '\uD835', '\uDD1E'); + put("Agrave", '\u00C0'); + put("agrave", '\u00E0'); + put("alefsym", '\u2135'); + put("aleph", '\u2135'); + put("Alpha", '\u0391'); + put("alpha", '\u03B1'); + put("Amacr", '\u0100'); + put("amacr", '\u0101'); + put("amalg", '\u2A3F'); + put("amp", '\u0026'); + put("AMP", '\u0026'); + put("andand", '\u2A55'); + put("And", '\u2A53'); + put("and", '\u2227'); + put("andd", '\u2A5C'); + put("andslope", '\u2A58'); + put("andv", '\u2A5A'); + put("ang", '\u2220'); + put("ange", '\u29A4'); + put("angle", '\u2220'); + put("angmsdaa", '\u29A8'); + put("angmsdab", '\u29A9'); + put("angmsdac", '\u29AA'); + put("angmsdad", '\u29AB'); + put("angmsdae", '\u29AC'); + put("angmsdaf", '\u29AD'); + put("angmsdag", '\u29AE'); + put("angmsdah", '\u29AF'); + put("angmsd", '\u2221'); + put("angrt", '\u221F'); + put("angrtvb", '\u22BE'); + put("angrtvbd", '\u299D'); + put("angsph", '\u2222'); + put("angst", '\u00C5'); + put("angzarr", '\u237C'); + put("Aogon", '\u0104'); + put("aogon", '\u0105'); + put("Aopf", '\uD835', '\uDD38'); + put("aopf", '\uD835', '\uDD52'); + put("apacir", '\u2A6F'); + put("ap", '\u2248'); + put("apE", '\u2A70'); + put("ape", '\u224A'); + put("apid", '\u224B'); + put("apos", '\''); + put("ApplyFunction", '\u2061'); + put("approx", '\u2248'); + put("approxeq", '\u224A'); + put("Aring", '\u00C5'); + put("aring", '\u00E5'); + put("Ascr", '\uD835', '\uDC9C'); + put("ascr", '\uD835', '\uDCB6'); + put("Assign", '\u2254'); + put("ast", '\u002A'); + put("asymp", '\u2248'); + put("asympeq", '\u224D'); + put("Atilde", '\u00C3'); + put("atilde", '\u00E3'); + put("Auml", '\u00C4'); + put("auml", '\u00E4'); + put("awconint", '\u2233'); + put("awint", '\u2A11'); + put("backcong", '\u224C'); + put("backepsilon", '\u03F6'); + put("backprime", '\u2035'); + put("backsim", '\u223D'); + put("backsimeq", '\u22CD'); + put("Backslash", '\u2216'); + put("Barv", '\u2AE7'); + put("barvee", '\u22BD'); + put("barwed", '\u2305'); + put("Barwed", '\u2306'); + put("barwedge", '\u2305'); + put("bbrk", '\u23B5'); + put("bbrktbrk", '\u23B6'); + put("bcong", '\u224C'); + put("Bcy", '\u0411'); + put("bcy", '\u0431'); + put("bdquo", '\u201E'); + put("becaus", '\u2235'); + put("because", '\u2235'); + put("Because", '\u2235'); + put("bemptyv", '\u29B0'); + put("bepsi", '\u03F6'); + put("bernou", '\u212C'); + put("Bernoullis", '\u212C'); + put("Beta", '\u0392'); + put("beta", '\u03B2'); + put("beth", '\u2136'); + put("between", '\u226C'); + put("Bfr", '\uD835', '\uDD05'); + put("bfr", '\uD835', '\uDD1F'); + put("bigcap", '\u22C2'); + put("bigcirc", '\u25EF'); + put("bigcup", '\u22C3'); + put("bigodot", '\u2A00'); + put("bigoplus", '\u2A01'); + put("bigotimes", '\u2A02'); + put("bigsqcup", '\u2A06'); + put("bigstar", '\u2605'); + put("bigtriangledown", '\u25BD'); + put("bigtriangleup", '\u25B3'); + put("biguplus", '\u2A04'); + put("bigvee", '\u22C1'); + put("bigwedge", '\u22C0'); + put("bkarow", '\u290D'); + put("blacklozenge", '\u29EB'); + put("blacksquare", '\u25AA'); + put("blacktriangle", '\u25B4'); + put("blacktriangledown", '\u25BE'); + put("blacktriangleleft", '\u25C2'); + put("blacktriangleright", '\u25B8'); + put("blank", '\u2423'); + put("blk12", '\u2592'); + put("blk14", '\u2591'); + put("blk34", '\u2593'); + put("block", '\u2588'); + put("bne", '\u003D', '\u20E5'); + put("bnequiv", '\u2261', '\u20E5'); + put("bNot", '\u2AED'); + put("bnot", '\u2310'); + put("Bopf", '\uD835', '\uDD39'); + put("bopf", '\uD835', '\uDD53'); + put("bot", '\u22A5'); + put("bottom", '\u22A5'); + put("bowtie", '\u22C8'); + put("boxbox", '\u29C9'); + put("boxdl", '\u2510'); + put("boxdL", '\u2555'); + put("boxDl", '\u2556'); + put("boxDL", '\u2557'); + put("boxdr", '\u250C'); + put("boxdR", '\u2552'); + put("boxDr", '\u2553'); + put("boxDR", '\u2554'); + put("boxh", '\u2500'); + put("boxH", '\u2550'); + put("boxhd", '\u252C'); + put("boxHd", '\u2564'); + put("boxhD", '\u2565'); + put("boxHD", '\u2566'); + put("boxhu", '\u2534'); + put("boxHu", '\u2567'); + put("boxhU", '\u2568'); + put("boxHU", '\u2569'); + put("boxminus", '\u229F'); + put("boxplus", '\u229E'); + put("boxtimes", '\u22A0'); + put("boxul", '\u2518'); + put("boxuL", '\u255B'); + put("boxUl", '\u255C'); + put("boxUL", '\u255D'); + put("boxur", '\u2514'); + put("boxuR", '\u2558'); + put("boxUr", '\u2559'); + put("boxUR", '\u255A'); + put("boxv", '\u2502'); + put("boxV", '\u2551'); + put("boxvh", '\u253C'); + put("boxvH", '\u256A'); + put("boxVh", '\u256B'); + put("boxVH", '\u256C'); + put("boxvl", '\u2524'); + put("boxvL", '\u2561'); + put("boxVl", '\u2562'); + put("boxVL", '\u2563'); + put("boxvr", '\u251C'); + put("boxvR", '\u255E'); + put("boxVr", '\u255F'); + put("boxVR", '\u2560'); + put("bprime", '\u2035'); + put("breve", '\u02D8'); + put("Breve", '\u02D8'); + put("brvbar", '\u00A6'); + put("bscr", '\uD835', '\uDCB7'); + put("Bscr", '\u212C'); + put("bsemi", '\u204F'); + put("bsim", '\u223D'); + put("bsime", '\u22CD'); + put("bsolb", '\u29C5'); + put("bsol", '\\'); + put("bsolhsub", '\u27C8'); + put("bull", '\u2022'); + put("bullet", '\u2022'); + put("bump", '\u224E'); + put("bumpE", '\u2AAE'); + put("bumpe", '\u224F'); + put("Bumpeq", '\u224E'); + put("bumpeq", '\u224F'); + put("Cacute", '\u0106'); + put("cacute", '\u0107'); + put("capand", '\u2A44'); + put("capbrcup", '\u2A49'); + put("capcap", '\u2A4B'); + put("cap", '\u2229'); + put("Cap", '\u22D2'); + put("capcup", '\u2A47'); + put("capdot", '\u2A40'); + put("CapitalDifferentialD", '\u2145'); + put("caps", '\u2229', '\uFE00'); + put("caret", '\u2041'); + put("caron", '\u02C7'); + put("Cayleys", '\u212D'); + put("ccaps", '\u2A4D'); + put("Ccaron", '\u010C'); + put("ccaron", '\u010D'); + put("Ccedil", '\u00C7'); + put("ccedil", '\u00E7'); + put("Ccirc", '\u0108'); + put("ccirc", '\u0109'); + put("Cconint", '\u2230'); + put("ccups", '\u2A4C'); + put("ccupssm", '\u2A50'); + put("Cdot", '\u010A'); + put("cdot", '\u010B'); + put("cedil", '\u00B8'); + put("Cedilla", '\u00B8'); + put("cemptyv", '\u29B2'); + put("cent", '\u00A2'); + put("centerdot", '\u00B7'); + put("CenterDot", '\u00B7'); + put("cfr", '\uD835', '\uDD20'); + put("Cfr", '\u212D'); + put("CHcy", '\u0427'); + put("chcy", '\u0447'); + put("check", '\u2713'); + put("checkmark", '\u2713'); + put("Chi", '\u03A7'); + put("chi", '\u03C7'); + put("circ", '\u02C6'); + put("circeq", '\u2257'); + put("circlearrowleft", '\u21BA'); + put("circlearrowright", '\u21BB'); + put("circledast", '\u229B'); + put("circledcirc", '\u229A'); + put("circleddash", '\u229D'); + put("CircleDot", '\u2299'); + put("circledR", '\u00AE'); + put("circledS", '\u24C8'); + put("CircleMinus", '\u2296'); + put("CirclePlus", '\u2295'); + put("CircleTimes", '\u2297'); + put("cir", '\u25CB'); + put("cirE", '\u29C3'); + put("cire", '\u2257'); + put("cirfnint", '\u2A10'); + put("cirmid", '\u2AEF'); + put("cirscir", '\u29C2'); + put("ClockwiseContourIntegral", '\u2232'); + put("CloseCurlyDoubleQuote", '\u201D'); + put("CloseCurlyQuote", '\u2019'); + put("clubs", '\u2663'); + put("clubsuit", '\u2663'); + put("colon", '\u003A'); + put("Colon", '\u2237'); + put("Colone", '\u2A74'); + put("colone", '\u2254'); + put("coloneq", '\u2254'); + put("comma", '\u002C'); + put("commat", '\u0040'); + put("comp", '\u2201'); + put("compfn", '\u2218'); + put("complement", '\u2201'); + put("complexes", '\u2102'); + put("cong", '\u2245'); + put("congdot", '\u2A6D'); + put("Congruent", '\u2261'); + put("conint", '\u222E'); + put("Conint", '\u222F'); + put("ContourIntegral", '\u222E'); + put("copf", '\uD835', '\uDD54'); + put("Copf", '\u2102'); + put("coprod", '\u2210'); + put("Coproduct", '\u2210'); + put("copy", '\u00A9'); + put("COPY", '\u00A9'); + put("copysr", '\u2117'); + put("CounterClockwiseContourIntegral", '\u2233'); + put("crarr", '\u21B5'); + put("cross", '\u2717'); + put("Cross", '\u2A2F'); + put("Cscr", '\uD835', '\uDC9E'); + put("cscr", '\uD835', '\uDCB8'); + put("csub", '\u2ACF'); + put("csube", '\u2AD1'); + put("csup", '\u2AD0'); + put("csupe", '\u2AD2'); + put("ctdot", '\u22EF'); + put("cudarrl", '\u2938'); + put("cudarrr", '\u2935'); + put("cuepr", '\u22DE'); + put("cuesc", '\u22DF'); + put("cularr", '\u21B6'); + put("cularrp", '\u293D'); + put("cupbrcap", '\u2A48'); + put("cupcap", '\u2A46'); + put("CupCap", '\u224D'); + put("cup", '\u222A'); + put("Cup", '\u22D3'); + put("cupcup", '\u2A4A'); + put("cupdot", '\u228D'); + put("cupor", '\u2A45'); + put("cups", '\u222A', '\uFE00'); + put("curarr", '\u21B7'); + put("curarrm", '\u293C'); + put("curlyeqprec", '\u22DE'); + put("curlyeqsucc", '\u22DF'); + put("curlyvee", '\u22CE'); + put("curlywedge", '\u22CF'); + put("curren", '\u00A4'); + put("curvearrowleft", '\u21B6'); + put("curvearrowright", '\u21B7'); + put("cuvee", '\u22CE'); + put("cuwed", '\u22CF'); + put("cwconint", '\u2232'); + put("cwint", '\u2231'); + put("cylcty", '\u232D'); + put("dagger", '\u2020'); + put("Dagger", '\u2021'); + put("daleth", '\u2138'); + put("darr", '\u2193'); + put("Darr", '\u21A1'); + put("dArr", '\u21D3'); + put("dash", '\u2010'); + put("Dashv", '\u2AE4'); + put("dashv", '\u22A3'); + put("dbkarow", '\u290F'); + put("dblac", '\u02DD'); + put("Dcaron", '\u010E'); + put("dcaron", '\u010F'); + put("Dcy", '\u0414'); + put("dcy", '\u0434'); + put("ddagger", '\u2021'); + put("ddarr", '\u21CA'); + put("DD", '\u2145'); + put("dd", '\u2146'); + put("DDotrahd", '\u2911'); + put("ddotseq", '\u2A77'); + put("deg", '\u00B0'); + put("Del", '\u2207'); + put("Delta", '\u0394'); + put("delta", '\u03B4'); + put("demptyv", '\u29B1'); + put("dfisht", '\u297F'); + put("Dfr", '\uD835', '\uDD07'); + put("dfr", '\uD835', '\uDD21'); + put("dHar", '\u2965'); + put("dharl", '\u21C3'); + put("dharr", '\u21C2'); + put("DiacriticalAcute", '\u00B4'); + put("DiacriticalDot", '\u02D9'); + put("DiacriticalDoubleAcute", '\u02DD'); + put("DiacriticalGrave", '\u0060'); + put("DiacriticalTilde", '\u02DC'); + put("diam", '\u22C4'); + put("diamond", '\u22C4'); + put("Diamond", '\u22C4'); + put("diamondsuit", '\u2666'); + put("diams", '\u2666'); + put("die", '\u00A8'); + put("DifferentialD", '\u2146'); + put("digamma", '\u03DD'); + put("disin", '\u22F2'); + put("div", '\u00F7'); + put("divide", '\u00F7'); + put("divideontimes", '\u22C7'); + put("divonx", '\u22C7'); + put("DJcy", '\u0402'); + put("djcy", '\u0452'); + put("dlcorn", '\u231E'); + put("dlcrop", '\u230D'); + put("dollar", '\u0024'); + put("Dopf", '\uD835', '\uDD3B'); + put("dopf", '\uD835', '\uDD55'); + put("Dot", '\u00A8'); + put("dot", '\u02D9'); + put("DotDot", '\u20DC'); + put("doteq", '\u2250'); + put("doteqdot", '\u2251'); + put("DotEqual", '\u2250'); + put("dotminus", '\u2238'); + put("dotplus", '\u2214'); + put("dotsquare", '\u22A1'); + put("doublebarwedge", '\u2306'); + put("DoubleContourIntegral", '\u222F'); + put("DoubleDot", '\u00A8'); + put("DoubleDownArrow", '\u21D3'); + put("DoubleLeftArrow", '\u21D0'); + put("DoubleLeftRightArrow", '\u21D4'); + put("DoubleLeftTee", '\u2AE4'); + put("DoubleLongLeftArrow", '\u27F8'); + put("DoubleLongLeftRightArrow", '\u27FA'); + put("DoubleLongRightArrow", '\u27F9'); + put("DoubleRightArrow", '\u21D2'); + put("DoubleRightTee", '\u22A8'); + put("DoubleUpArrow", '\u21D1'); + put("DoubleUpDownArrow", '\u21D5'); + put("DoubleVerticalBar", '\u2225'); + put("DownArrowBar", '\u2913'); + put("downarrow", '\u2193'); + put("DownArrow", '\u2193'); + put("Downarrow", '\u21D3'); + put("DownArrowUpArrow", '\u21F5'); + put("DownBreve", '\u0311'); + put("downdownarrows", '\u21CA'); + put("downharpoonleft", '\u21C3'); + put("downharpoonright", '\u21C2'); + put("DownLeftRightVector", '\u2950'); + put("DownLeftTeeVector", '\u295E'); + put("DownLeftVectorBar", '\u2956'); + put("DownLeftVector", '\u21BD'); + put("DownRightTeeVector", '\u295F'); + put("DownRightVectorBar", '\u2957'); + put("DownRightVector", '\u21C1'); + put("DownTeeArrow", '\u21A7'); + put("DownTee", '\u22A4'); + put("drbkarow", '\u2910'); + put("drcorn", '\u231F'); + put("drcrop", '\u230C'); + put("Dscr", '\uD835', '\uDC9F'); + put("dscr", '\uD835', '\uDCB9'); + put("DScy", '\u0405'); + put("dscy", '\u0455'); + put("dsol", '\u29F6'); + put("Dstrok", '\u0110'); + put("dstrok", '\u0111'); + put("dtdot", '\u22F1'); + put("dtri", '\u25BF'); + put("dtrif", '\u25BE'); + put("duarr", '\u21F5'); + put("duhar", '\u296F'); + put("dwangle", '\u29A6'); + put("DZcy", '\u040F'); + put("dzcy", '\u045F'); + put("dzigrarr", '\u27FF'); + put("Eacute", '\u00C9'); + put("eacute", '\u00E9'); + put("easter", '\u2A6E'); + put("Ecaron", '\u011A'); + put("ecaron", '\u011B'); + put("Ecirc", '\u00CA'); + put("ecirc", '\u00EA'); + put("ecir", '\u2256'); + put("ecolon", '\u2255'); + put("Ecy", '\u042D'); + put("ecy", '\u044D'); + put("eDDot", '\u2A77'); + put("Edot", '\u0116'); + put("edot", '\u0117'); + put("eDot", '\u2251'); + put("ee", '\u2147'); + put("efDot", '\u2252'); + put("Efr", '\uD835', '\uDD08'); + put("efr", '\uD835', '\uDD22'); + put("eg", '\u2A9A'); + put("Egrave", '\u00C8'); + put("egrave", '\u00E8'); + put("egs", '\u2A96'); + put("egsdot", '\u2A98'); + put("el", '\u2A99'); + put("Element", '\u2208'); + put("elinters", '\u23E7'); + put("ell", '\u2113'); + put("els", '\u2A95'); + put("elsdot", '\u2A97'); + put("Emacr", '\u0112'); + put("emacr", '\u0113'); + put("empty", '\u2205'); + put("emptyset", '\u2205'); + put("EmptySmallSquare", '\u25FB'); + put("emptyv", '\u2205'); + put("EmptyVerySmallSquare", '\u25AB'); + put("emsp13", '\u2004'); + put("emsp14", '\u2005'); + put("emsp", '\u2003'); + put("ENG", '\u014A'); + put("eng", '\u014B'); + put("ensp", '\u2002'); + put("Eogon", '\u0118'); + put("eogon", '\u0119'); + put("Eopf", '\uD835', '\uDD3C'); + put("eopf", '\uD835', '\uDD56'); + put("epar", '\u22D5'); + put("eparsl", '\u29E3'); + put("eplus", '\u2A71'); + put("epsi", '\u03B5'); + put("Epsilon", '\u0395'); + put("epsilon", '\u03B5'); + put("epsiv", '\u03F5'); + put("eqcirc", '\u2256'); + put("eqcolon", '\u2255'); + put("eqsim", '\u2242'); + put("eqslantgtr", '\u2A96'); + put("eqslantless", '\u2A95'); + put("Equal", '\u2A75'); + put("equals", '\u003D'); + put("EqualTilde", '\u2242'); + put("equest", '\u225F'); + put("Equilibrium", '\u21CC'); + put("equiv", '\u2261'); + put("equivDD", '\u2A78'); + put("eqvparsl", '\u29E5'); + put("erarr", '\u2971'); + put("erDot", '\u2253'); + put("escr", '\u212F'); + put("Escr", '\u2130'); + put("esdot", '\u2250'); + put("Esim", '\u2A73'); + put("esim", '\u2242'); + put("Eta", '\u0397'); + put("eta", '\u03B7'); + put("ETH", '\u00D0'); + put("eth", '\u00F0'); + put("Euml", '\u00CB'); + put("euml", '\u00EB'); + put("euro", '\u20AC'); + put("excl", '\u0021'); + put("exist", '\u2203'); + put("Exists", '\u2203'); + put("expectation", '\u2130'); + put("exponentiale", '\u2147'); + put("ExponentialE", '\u2147'); + put("fallingdotseq", '\u2252'); + put("Fcy", '\u0424'); + put("fcy", '\u0444'); + put("female", '\u2640'); + put("ffilig", '\uFB03'); + put("fflig", '\uFB00'); + put("ffllig", '\uFB04'); + put("Ffr", '\uD835', '\uDD09'); + put("ffr", '\uD835', '\uDD23'); + put("filig", '\uFB01'); + put("FilledSmallSquare", '\u25FC'); + put("FilledVerySmallSquare", '\u25AA'); + put("fjlig", '\u0066', '\u006A'); + put("flat", '\u266D'); + put("fllig", '\uFB02'); + put("fltns", '\u25B1'); + put("fnof", '\u0192'); + put("Fopf", '\uD835', '\uDD3D'); + put("fopf", '\uD835', '\uDD57'); + put("forall", '\u2200'); + put("ForAll", '\u2200'); + put("fork", '\u22D4'); + put("forkv", '\u2AD9'); + put("Fouriertrf", '\u2131'); + put("fpartint", '\u2A0D'); + put("frac12", '\u00BD'); + put("frac13", '\u2153'); + put("frac14", '\u00BC'); + put("frac15", '\u2155'); + put("frac16", '\u2159'); + put("frac18", '\u215B'); + put("frac23", '\u2154'); + put("frac25", '\u2156'); + put("frac34", '\u00BE'); + put("frac35", '\u2157'); + put("frac38", '\u215C'); + put("frac45", '\u2158'); + put("frac56", '\u215A'); + put("frac58", '\u215D'); + put("frac78", '\u215E'); + put("frasl", '\u2044'); + put("frown", '\u2322'); + put("fscr", '\uD835', '\uDCBB'); + put("Fscr", '\u2131'); + put("gacute", '\u01F5'); + put("Gamma", '\u0393'); + put("gamma", '\u03B3'); + put("Gammad", '\u03DC'); + put("gammad", '\u03DD'); + put("gap", '\u2A86'); + put("Gbreve", '\u011E'); + put("gbreve", '\u011F'); + put("Gcedil", '\u0122'); + put("Gcirc", '\u011C'); + put("gcirc", '\u011D'); + put("Gcy", '\u0413'); + put("gcy", '\u0433'); + put("Gdot", '\u0120'); + put("gdot", '\u0121'); + put("ge", '\u2265'); + put("gE", '\u2267'); + put("gEl", '\u2A8C'); + put("gel", '\u22DB'); + put("geq", '\u2265'); + put("geqq", '\u2267'); + put("geqslant", '\u2A7E'); + put("gescc", '\u2AA9'); + put("ges", '\u2A7E'); + put("gesdot", '\u2A80'); + put("gesdoto", '\u2A82'); + put("gesdotol", '\u2A84'); + put("gesl", '\u22DB', '\uFE00'); + put("gesles", '\u2A94'); + put("Gfr", '\uD835', '\uDD0A'); + put("gfr", '\uD835', '\uDD24'); + put("gg", '\u226B'); + put("Gg", '\u22D9'); + put("ggg", '\u22D9'); + put("gimel", '\u2137'); + put("GJcy", '\u0403'); + put("gjcy", '\u0453'); + put("gla", '\u2AA5'); + put("gl", '\u2277'); + put("glE", '\u2A92'); + put("glj", '\u2AA4'); + put("gnap", '\u2A8A'); + put("gnapprox", '\u2A8A'); + put("gne", '\u2A88'); + put("gnE", '\u2269'); + put("gneq", '\u2A88'); + put("gneqq", '\u2269'); + put("gnsim", '\u22E7'); + put("Gopf", '\uD835', '\uDD3E'); + put("gopf", '\uD835', '\uDD58'); + put("grave", '\u0060'); + put("GreaterEqual", '\u2265'); + put("GreaterEqualLess", '\u22DB'); + put("GreaterFullEqual", '\u2267'); + put("GreaterGreater", '\u2AA2'); + put("GreaterLess", '\u2277'); + put("GreaterSlantEqual", '\u2A7E'); + put("GreaterTilde", '\u2273'); + put("Gscr", '\uD835', '\uDCA2'); + put("gscr", '\u210A'); + put("gsim", '\u2273'); + put("gsime", '\u2A8E'); + put("gsiml", '\u2A90'); + put("gtcc", '\u2AA7'); + put("gtcir", '\u2A7A'); + put("gt", '\u003E'); + put("GT", '\u003E'); + put("Gt", '\u226B'); + put("gtdot", '\u22D7'); + put("gtlPar", '\u2995'); + put("gtquest", '\u2A7C'); + put("gtrapprox", '\u2A86'); + put("gtrarr", '\u2978'); + put("gtrdot", '\u22D7'); + put("gtreqless", '\u22DB'); + put("gtreqqless", '\u2A8C'); + put("gtrless", '\u2277'); + put("gtrsim", '\u2273'); + put("gvertneqq", '\u2269', '\uFE00'); + put("gvnE", '\u2269', '\uFE00'); + put("Hacek", '\u02C7'); + put("hairsp", '\u200A'); + put("half", '\u00BD'); + put("hamilt", '\u210B'); + put("HARDcy", '\u042A'); + put("hardcy", '\u044A'); + put("harrcir", '\u2948'); + put("harr", '\u2194'); + put("hArr", '\u21D4'); + put("harrw", '\u21AD'); + put("Hat", '\u005E'); + put("hbar", '\u210F'); + put("Hcirc", '\u0124'); + put("hcirc", '\u0125'); + put("hearts", '\u2665'); + put("heartsuit", '\u2665'); + put("hellip", '\u2026'); + put("hercon", '\u22B9'); + put("hfr", '\uD835', '\uDD25'); + put("Hfr", '\u210C'); + put("HilbertSpace", '\u210B'); + put("hksearow", '\u2925'); + put("hkswarow", '\u2926'); + put("hoarr", '\u21FF'); + put("homtht", '\u223B'); + put("hookleftarrow", '\u21A9'); + put("hookrightarrow", '\u21AA'); + put("hopf", '\uD835', '\uDD59'); + put("Hopf", '\u210D'); + put("horbar", '\u2015'); + put("HorizontalLine", '\u2500'); + put("hscr", '\uD835', '\uDCBD'); + put("Hscr", '\u210B'); + put("hslash", '\u210F'); + put("Hstrok", '\u0126'); + put("hstrok", '\u0127'); + put("HumpDownHump", '\u224E'); + put("HumpEqual", '\u224F'); + put("hybull", '\u2043'); + put("hyphen", '\u2010'); + put("Iacute", '\u00CD'); + put("iacute", '\u00ED'); + put("ic", '\u2063'); + put("Icirc", '\u00CE'); + put("icirc", '\u00EE'); + put("Icy", '\u0418'); + put("icy", '\u0438'); + put("Idot", '\u0130'); + put("IEcy", '\u0415'); + put("iecy", '\u0435'); + put("iexcl", '\u00A1'); + put("iff", '\u21D4'); + put("ifr", '\uD835', '\uDD26'); + put("Ifr", '\u2111'); + put("Igrave", '\u00CC'); + put("igrave", '\u00EC'); + put("ii", '\u2148'); + put("iiiint", '\u2A0C'); + put("iiint", '\u222D'); + put("iinfin", '\u29DC'); + put("iiota", '\u2129'); + put("IJlig", '\u0132'); + put("ijlig", '\u0133'); + put("Imacr", '\u012A'); + put("imacr", '\u012B'); + put("image", '\u2111'); + put("ImaginaryI", '\u2148'); + put("imagline", '\u2110'); + put("imagpart", '\u2111'); + put("imath", '\u0131'); + put("Im", '\u2111'); + put("imof", '\u22B7'); + put("imped", '\u01B5'); + put("Implies", '\u21D2'); + put("incare", '\u2105'); + put("in", '\u2208'); + put("infin", '\u221E'); + put("infintie", '\u29DD'); + put("inodot", '\u0131'); + put("intcal", '\u22BA'); + put("int", '\u222B'); + put("Int", '\u222C'); + put("integers", '\u2124'); + put("Integral", '\u222B'); + put("intercal", '\u22BA'); + put("Intersection", '\u22C2'); + put("intlarhk", '\u2A17'); + put("intprod", '\u2A3C'); + put("InvisibleComma", '\u2063'); + put("InvisibleTimes", '\u2062'); + put("IOcy", '\u0401'); + put("iocy", '\u0451'); + put("Iogon", '\u012E'); + put("iogon", '\u012F'); + put("Iopf", '\uD835', '\uDD40'); + put("iopf", '\uD835', '\uDD5A'); + put("Iota", '\u0399'); + put("iota", '\u03B9'); + put("iprod", '\u2A3C'); + put("iquest", '\u00BF'); + put("iscr", '\uD835', '\uDCBE'); + put("Iscr", '\u2110'); + put("isin", '\u2208'); + put("isindot", '\u22F5'); + put("isinE", '\u22F9'); + put("isins", '\u22F4'); + put("isinsv", '\u22F3'); + put("isinv", '\u2208'); + put("it", '\u2062'); + put("Itilde", '\u0128'); + put("itilde", '\u0129'); + put("Iukcy", '\u0406'); + put("iukcy", '\u0456'); + put("Iuml", '\u00CF'); + put("iuml", '\u00EF'); + put("Jcirc", '\u0134'); + put("jcirc", '\u0135'); + put("Jcy", '\u0419'); + put("jcy", '\u0439'); + put("Jfr", '\uD835', '\uDD0D'); + put("jfr", '\uD835', '\uDD27'); + put("jmath", '\u0237'); + put("Jopf", '\uD835', '\uDD41'); + put("jopf", '\uD835', '\uDD5B'); + put("Jscr", '\uD835', '\uDCA5'); + put("jscr", '\uD835', '\uDCBF'); + put("Jsercy", '\u0408'); + put("jsercy", '\u0458'); + put("Jukcy", '\u0404'); + put("jukcy", '\u0454'); + put("Kappa", '\u039A'); + put("kappa", '\u03BA'); + put("kappav", '\u03F0'); + put("Kcedil", '\u0136'); + put("kcedil", '\u0137'); + put("Kcy", '\u041A'); + put("kcy", '\u043A'); + put("Kfr", '\uD835', '\uDD0E'); + put("kfr", '\uD835', '\uDD28'); + put("kgreen", '\u0138'); + put("KHcy", '\u0425'); + put("khcy", '\u0445'); + put("KJcy", '\u040C'); + put("kjcy", '\u045C'); + put("Kopf", '\uD835', '\uDD42'); + put("kopf", '\uD835', '\uDD5C'); + put("Kscr", '\uD835', '\uDCA6'); + put("kscr", '\uD835', '\uDCC0'); + put("lAarr", '\u21DA'); + put("Lacute", '\u0139'); + put("lacute", '\u013A'); + put("laemptyv", '\u29B4'); + put("lagran", '\u2112'); + put("Lambda", '\u039B'); + put("lambda", '\u03BB'); + put("lang", '\u27E8'); + put("Lang", '\u27EA'); + put("langd", '\u2991'); + put("langle", '\u27E8'); + put("lap", '\u2A85'); + put("Laplacetrf", '\u2112'); + put("laquo", '\u00AB'); + put("larrb", '\u21E4'); + put("larrbfs", '\u291F'); + put("larr", '\u2190'); + put("Larr", '\u219E'); + put("lArr", '\u21D0'); + put("larrfs", '\u291D'); + put("larrhk", '\u21A9'); + put("larrlp", '\u21AB'); + put("larrpl", '\u2939'); + put("larrsim", '\u2973'); + put("larrtl", '\u21A2'); + put("latail", '\u2919'); + put("lAtail", '\u291B'); + put("lat", '\u2AAB'); + put("late", '\u2AAD'); + put("lates", '\u2AAD', '\uFE00'); + put("lbarr", '\u290C'); + put("lBarr", '\u290E'); + put("lbbrk", '\u2772'); + put("lbrace", '\u007B'); + put("lbrack", '\u005B'); + put("lbrke", '\u298B'); + put("lbrksld", '\u298F'); + put("lbrkslu", '\u298D'); + put("Lcaron", '\u013D'); + put("lcaron", '\u013E'); + put("Lcedil", '\u013B'); + put("lcedil", '\u013C'); + put("lceil", '\u2308'); + put("lcub", '\u007B'); + put("Lcy", '\u041B'); + put("lcy", '\u043B'); + put("ldca", '\u2936'); + put("ldquo", '\u201C'); + put("ldquor", '\u201E'); + put("ldrdhar", '\u2967'); + put("ldrushar", '\u294B'); + put("ldsh", '\u21B2'); + put("le", '\u2264'); + put("lE", '\u2266'); + put("LeftAngleBracket", '\u27E8'); + put("LeftArrowBar", '\u21E4'); + put("leftarrow", '\u2190'); + put("LeftArrow", '\u2190'); + put("Leftarrow", '\u21D0'); + put("LeftArrowRightArrow", '\u21C6'); + put("leftarrowtail", '\u21A2'); + put("LeftCeiling", '\u2308'); + put("LeftDoubleBracket", '\u27E6'); + put("LeftDownTeeVector", '\u2961'); + put("LeftDownVectorBar", '\u2959'); + put("LeftDownVector", '\u21C3'); + put("LeftFloor", '\u230A'); + put("leftharpoondown", '\u21BD'); + put("leftharpoonup", '\u21BC'); + put("leftleftarrows", '\u21C7'); + put("leftrightarrow", '\u2194'); + put("LeftRightArrow", '\u2194'); + put("Leftrightarrow", '\u21D4'); + put("leftrightarrows", '\u21C6'); + put("leftrightharpoons", '\u21CB'); + put("leftrightsquigarrow", '\u21AD'); + put("LeftRightVector", '\u294E'); + put("LeftTeeArrow", '\u21A4'); + put("LeftTee", '\u22A3'); + put("LeftTeeVector", '\u295A'); + put("leftthreetimes", '\u22CB'); + put("LeftTriangleBar", '\u29CF'); + put("LeftTriangle", '\u22B2'); + put("LeftTriangleEqual", '\u22B4'); + put("LeftUpDownVector", '\u2951'); + put("LeftUpTeeVector", '\u2960'); + put("LeftUpVectorBar", '\u2958'); + put("LeftUpVector", '\u21BF'); + put("LeftVectorBar", '\u2952'); + put("LeftVector", '\u21BC'); + put("lEg", '\u2A8B'); + put("leg", '\u22DA'); + put("leq", '\u2264'); + put("leqq", '\u2266'); + put("leqslant", '\u2A7D'); + put("lescc", '\u2AA8'); + put("les", '\u2A7D'); + put("lesdot", '\u2A7F'); + put("lesdoto", '\u2A81'); + put("lesdotor", '\u2A83'); + put("lesg", '\u22DA', '\uFE00'); + put("lesges", '\u2A93'); + put("lessapprox", '\u2A85'); + put("lessdot", '\u22D6'); + put("lesseqgtr", '\u22DA'); + put("lesseqqgtr", '\u2A8B'); + put("LessEqualGreater", '\u22DA'); + put("LessFullEqual", '\u2266'); + put("LessGreater", '\u2276'); + put("lessgtr", '\u2276'); + put("LessLess", '\u2AA1'); + put("lesssim", '\u2272'); + put("LessSlantEqual", '\u2A7D'); + put("LessTilde", '\u2272'); + put("lfisht", '\u297C'); + put("lfloor", '\u230A'); + put("Lfr", '\uD835', '\uDD0F'); + put("lfr", '\uD835', '\uDD29'); + put("lg", '\u2276'); + put("lgE", '\u2A91'); + put("lHar", '\u2962'); + put("lhard", '\u21BD'); + put("lharu", '\u21BC'); + put("lharul", '\u296A'); + put("lhblk", '\u2584'); + put("LJcy", '\u0409'); + put("ljcy", '\u0459'); + put("llarr", '\u21C7'); + put("ll", '\u226A'); + put("Ll", '\u22D8'); + put("llcorner", '\u231E'); + put("Lleftarrow", '\u21DA'); + put("llhard", '\u296B'); + put("lltri", '\u25FA'); + put("Lmidot", '\u013F'); + put("lmidot", '\u0140'); + put("lmoustache", '\u23B0'); + put("lmoust", '\u23B0'); + put("lnap", '\u2A89'); + put("lnapprox", '\u2A89'); + put("lne", '\u2A87'); + put("lnE", '\u2268'); + put("lneq", '\u2A87'); + put("lneqq", '\u2268'); + put("lnsim", '\u22E6'); + put("loang", '\u27EC'); + put("loarr", '\u21FD'); + put("lobrk", '\u27E6'); + put("longleftarrow", '\u27F5'); + put("LongLeftArrow", '\u27F5'); + put("Longleftarrow", '\u27F8'); + put("longleftrightarrow", '\u27F7'); + put("LongLeftRightArrow", '\u27F7'); + put("Longleftrightarrow", '\u27FA'); + put("longmapsto", '\u27FC'); + put("longrightarrow", '\u27F6'); + put("LongRightArrow", '\u27F6'); + put("Longrightarrow", '\u27F9'); + put("looparrowleft", '\u21AB'); + put("looparrowright", '\u21AC'); + put("lopar", '\u2985'); + put("Lopf", '\uD835', '\uDD43'); + put("lopf", '\uD835', '\uDD5D'); + put("loplus", '\u2A2D'); + put("lotimes", '\u2A34'); + put("lowast", '\u2217'); + put("lowbar", '\u005F'); + put("LowerLeftArrow", '\u2199'); + put("LowerRightArrow", '\u2198'); + put("loz", '\u25CA'); + put("lozenge", '\u25CA'); + put("lozf", '\u29EB'); + put("lpar", '\u0028'); + put("lparlt", '\u2993'); + put("lrarr", '\u21C6'); + put("lrcorner", '\u231F'); + put("lrhar", '\u21CB'); + put("lrhard", '\u296D'); + put("lrm", '\u200E'); + put("lrtri", '\u22BF'); + put("lsaquo", '\u2039'); + put("lscr", '\uD835', '\uDCC1'); + put("Lscr", '\u2112'); + put("lsh", '\u21B0'); + put("Lsh", '\u21B0'); + put("lsim", '\u2272'); + put("lsime", '\u2A8D'); + put("lsimg", '\u2A8F'); + put("lsqb", '\u005B'); + put("lsquo", '\u2018'); + put("lsquor", '\u201A'); + put("Lstrok", '\u0141'); + put("lstrok", '\u0142'); + put("ltcc", '\u2AA6'); + put("ltcir", '\u2A79'); + put("lt", '\u003C'); + put("LT", '\u003C'); + put("Lt", '\u226A'); + put("ltdot", '\u22D6'); + put("lthree", '\u22CB'); + put("ltimes", '\u22C9'); + put("ltlarr", '\u2976'); + put("ltquest", '\u2A7B'); + put("ltri", '\u25C3'); + put("ltrie", '\u22B4'); + put("ltrif", '\u25C2'); + put("ltrPar", '\u2996'); + put("lurdshar", '\u294A'); + put("luruhar", '\u2966'); + put("lvertneqq", '\u2268', '\uFE00'); + put("lvnE", '\u2268', '\uFE00'); + put("macr", '\u00AF'); + put("male", '\u2642'); + put("malt", '\u2720'); + put("maltese", '\u2720'); + put("Map", '\u2905'); + put("map", '\u21A6'); + put("mapsto", '\u21A6'); + put("mapstodown", '\u21A7'); + put("mapstoleft", '\u21A4'); + put("mapstoup", '\u21A5'); + put("marker", '\u25AE'); + put("mcomma", '\u2A29'); + put("Mcy", '\u041C'); + put("mcy", '\u043C'); + put("mdash", '\u2014'); + put("mDDot", '\u223A'); + put("measuredangle", '\u2221'); + put("MediumSpace", '\u205F'); + put("Mellintrf", '\u2133'); + put("Mfr", '\uD835', '\uDD10'); + put("mfr", '\uD835', '\uDD2A'); + put("mho", '\u2127'); + put("micro", '\u00B5'); + put("midast", '\u002A'); + put("midcir", '\u2AF0'); + put("mid", '\u2223'); + put("middot", '\u00B7'); + put("minusb", '\u229F'); + put("minus", '\u2212'); + put("minusd", '\u2238'); + put("minusdu", '\u2A2A'); + put("MinusPlus", '\u2213'); + put("mlcp", '\u2ADB'); + put("mldr", '\u2026'); + put("mnplus", '\u2213'); + put("models", '\u22A7'); + put("Mopf", '\uD835', '\uDD44'); + put("mopf", '\uD835', '\uDD5E'); + put("mp", '\u2213'); + put("mscr", '\uD835', '\uDCC2'); + put("Mscr", '\u2133'); + put("mstpos", '\u223E'); + put("Mu", '\u039C'); + put("mu", '\u03BC'); + put("multimap", '\u22B8'); + put("mumap", '\u22B8'); + put("nabla", '\u2207'); + put("Nacute", '\u0143'); + put("nacute", '\u0144'); + put("nang", '\u2220', '\u20D2'); + put("nap", '\u2249'); + put("napE", '\u2A70', '\u0338'); + put("napid", '\u224B', '\u0338'); + put("napos", '\u0149'); + put("napprox", '\u2249'); + put("natural", '\u266E'); + put("naturals", '\u2115'); + put("natur", '\u266E'); + put("nbsp", '\u00A0'); + put("nbump", '\u224E', '\u0338'); + put("nbumpe", '\u224F', '\u0338'); + put("ncap", '\u2A43'); + put("Ncaron", '\u0147'); + put("ncaron", '\u0148'); + put("Ncedil", '\u0145'); + put("ncedil", '\u0146'); + put("ncong", '\u2247'); + put("ncongdot", '\u2A6D', '\u0338'); + put("ncup", '\u2A42'); + put("Ncy", '\u041D'); + put("ncy", '\u043D'); + put("ndash", '\u2013'); + put("nearhk", '\u2924'); + put("nearr", '\u2197'); + put("neArr", '\u21D7'); + put("nearrow", '\u2197'); + put("ne", '\u2260'); + put("nedot", '\u2250', '\u0338'); + put("NegativeMediumSpace", '\u200B'); + put("NegativeThickSpace", '\u200B'); + put("NegativeThinSpace", '\u200B'); + put("NegativeVeryThinSpace", '\u200B'); + put("nequiv", '\u2262'); + put("nesear", '\u2928'); + put("nesim", '\u2242', '\u0338'); + put("NestedGreaterGreater", '\u226B'); + put("NestedLessLess", '\u226A'); + put("NewLine", '\n'); + put("nexist", '\u2204'); + put("nexists", '\u2204'); + put("Nfr", '\uD835', '\uDD11'); + put("nfr", '\uD835', '\uDD2B'); + put("ngE", '\u2267', '\u0338'); + put("nge", '\u2271'); + put("ngeq", '\u2271'); + put("ngeqq", '\u2267', '\u0338'); + put("ngeqslant", '\u2A7E', '\u0338'); + put("nges", '\u2A7E', '\u0338'); + put("nGg", '\u22D9', '\u0338'); + put("ngsim", '\u2275'); + put("nGt", '\u226B', '\u20D2'); + put("ngt", '\u226F'); + put("ngtr", '\u226F'); + put("nGtv", '\u226B', '\u0338'); + put("nharr", '\u21AE'); + put("nhArr", '\u21CE'); + put("nhpar", '\u2AF2'); + put("ni", '\u220B'); + put("nis", '\u22FC'); + put("nisd", '\u22FA'); + put("niv", '\u220B'); + put("NJcy", '\u040A'); + put("njcy", '\u045A'); + put("nlarr", '\u219A'); + put("nlArr", '\u21CD'); + put("nldr", '\u2025'); + put("nlE", '\u2266', '\u0338'); + put("nle", '\u2270'); + put("nleftarrow", '\u219A'); + put("nLeftarrow", '\u21CD'); + put("nleftrightarrow", '\u21AE'); + put("nLeftrightarrow", '\u21CE'); + put("nleq", '\u2270'); + put("nleqq", '\u2266', '\u0338'); + put("nleqslant", '\u2A7D', '\u0338'); + put("nles", '\u2A7D', '\u0338'); + put("nless", '\u226E'); + put("nLl", '\u22D8', '\u0338'); + put("nlsim", '\u2274'); + put("nLt", '\u226A', '\u20D2'); + put("nlt", '\u226E'); + put("nltri", '\u22EA'); + put("nltrie", '\u22EC'); + put("nLtv", '\u226A', '\u0338'); + put("nmid", '\u2224'); + put("NoBreak", '\u2060'); + put("NonBreakingSpace", '\u00A0'); + put("nopf", '\uD835', '\uDD5F'); + put("Nopf", '\u2115'); + put("Not", '\u2AEC'); + put("not", '\u00AC'); + put("NotCongruent", '\u2262'); + put("NotCupCap", '\u226D'); + put("NotDoubleVerticalBar", '\u2226'); + put("NotElement", '\u2209'); + put("NotEqual", '\u2260'); + put("NotEqualTilde", '\u2242', '\u0338'); + put("NotExists", '\u2204'); + put("NotGreater", '\u226F'); + put("NotGreaterEqual", '\u2271'); + put("NotGreaterFullEqual", '\u2267', '\u0338'); + put("NotGreaterGreater", '\u226B', '\u0338'); + put("NotGreaterLess", '\u2279'); + put("NotGreaterSlantEqual", '\u2A7E', '\u0338'); + put("NotGreaterTilde", '\u2275'); + put("NotHumpDownHump", '\u224E', '\u0338'); + put("NotHumpEqual", '\u224F', '\u0338'); + put("notin", '\u2209'); + put("notindot", '\u22F5', '\u0338'); + put("notinE", '\u22F9', '\u0338'); + put("notinva", '\u2209'); + put("notinvb", '\u22F7'); + put("notinvc", '\u22F6'); + put("NotLeftTriangleBar", '\u29CF', '\u0338'); + put("NotLeftTriangle", '\u22EA'); + put("NotLeftTriangleEqual", '\u22EC'); + put("NotLess", '\u226E'); + put("NotLessEqual", '\u2270'); + put("NotLessGreater", '\u2278'); + put("NotLessLess", '\u226A', '\u0338'); + put("NotLessSlantEqual", '\u2A7D', '\u0338'); + put("NotLessTilde", '\u2274'); + put("NotNestedGreaterGreater", '\u2AA2', '\u0338'); + put("NotNestedLessLess", '\u2AA1', '\u0338'); + put("notni", '\u220C'); + put("notniva", '\u220C'); + put("notnivb", '\u22FE'); + put("notnivc", '\u22FD'); + put("NotPrecedes", '\u2280'); + put("NotPrecedesEqual", '\u2AAF', '\u0338'); + put("NotPrecedesSlantEqual", '\u22E0'); + put("NotReverseElement", '\u220C'); + put("NotRightTriangleBar", '\u29D0', '\u0338'); + put("NotRightTriangle", '\u22EB'); + put("NotRightTriangleEqual", '\u22ED'); + put("NotSquareSubset", '\u228F', '\u0338'); + put("NotSquareSubsetEqual", '\u22E2'); + put("NotSquareSuperset", '\u2290', '\u0338'); + put("NotSquareSupersetEqual", '\u22E3'); + put("NotSubset", '\u2282', '\u20D2'); + put("NotSubsetEqual", '\u2288'); + put("NotSucceeds", '\u2281'); + put("NotSucceedsEqual", '\u2AB0', '\u0338'); + put("NotSucceedsSlantEqual", '\u22E1'); + put("NotSucceedsTilde", '\u227F', '\u0338'); + put("NotSuperset", '\u2283', '\u20D2'); + put("NotSupersetEqual", '\u2289'); + put("NotTilde", '\u2241'); + put("NotTildeEqual", '\u2244'); + put("NotTildeFullEqual", '\u2247'); + put("NotTildeTilde", '\u2249'); + put("NotVerticalBar", '\u2224'); + put("nparallel", '\u2226'); + put("npar", '\u2226'); + put("nparsl", '\u2AFD', '\u20E5'); + put("npart", '\u2202', '\u0338'); + put("npolint", '\u2A14'); + put("npr", '\u2280'); + put("nprcue", '\u22E0'); + put("nprec", '\u2280'); + put("npreceq", '\u2AAF', '\u0338'); + put("npre", '\u2AAF', '\u0338'); + put("nrarrc", '\u2933', '\u0338'); + put("nrarr", '\u219B'); + put("nrArr", '\u21CF'); + put("nrarrw", '\u219D', '\u0338'); + put("nrightarrow", '\u219B'); + put("nRightarrow", '\u21CF'); + put("nrtri", '\u22EB'); + put("nrtrie", '\u22ED'); + put("nsc", '\u2281'); + put("nsccue", '\u22E1'); + put("nsce", '\u2AB0', '\u0338'); + put("Nscr", '\uD835', '\uDCA9'); + put("nscr", '\uD835', '\uDCC3'); + put("nshortmid", '\u2224'); + put("nshortparallel", '\u2226'); + put("nsim", '\u2241'); + put("nsime", '\u2244'); + put("nsimeq", '\u2244'); + put("nsmid", '\u2224'); + put("nspar", '\u2226'); + put("nsqsube", '\u22E2'); + put("nsqsupe", '\u22E3'); + put("nsub", '\u2284'); + put("nsubE", '\u2AC5', '\u0338'); + put("nsube", '\u2288'); + put("nsubset", '\u2282', '\u20D2'); + put("nsubseteq", '\u2288'); + put("nsubseteqq", '\u2AC5', '\u0338'); + put("nsucc", '\u2281'); + put("nsucceq", '\u2AB0', '\u0338'); + put("nsup", '\u2285'); + put("nsupE", '\u2AC6', '\u0338'); + put("nsupe", '\u2289'); + put("nsupset", '\u2283', '\u20D2'); + put("nsupseteq", '\u2289'); + put("nsupseteqq", '\u2AC6', '\u0338'); + put("ntgl", '\u2279'); + put("Ntilde", '\u00D1'); + put("ntilde", '\u00F1'); + put("ntlg", '\u2278'); + put("ntriangleleft", '\u22EA'); + put("ntrianglelefteq", '\u22EC'); + put("ntriangleright", '\u22EB'); + put("ntrianglerighteq", '\u22ED'); + put("Nu", '\u039D'); + put("nu", '\u03BD'); + put("num", '\u0023'); + put("numero", '\u2116'); + put("numsp", '\u2007'); + put("nvap", '\u224D', '\u20D2'); + put("nvdash", '\u22AC'); + put("nvDash", '\u22AD'); + put("nVdash", '\u22AE'); + put("nVDash", '\u22AF'); + put("nvge", '\u2265', '\u20D2'); + put("nvgt", '\u003E', '\u20D2'); + put("nvHarr", '\u2904'); + put("nvinfin", '\u29DE'); + put("nvlArr", '\u2902'); + put("nvle", '\u2264', '\u20D2'); + put("nvlt", '\u003C', '\u20D2'); + put("nvltrie", '\u22B4', '\u20D2'); + put("nvrArr", '\u2903'); + put("nvrtrie", '\u22B5', '\u20D2'); + put("nvsim", '\u223C', '\u20D2'); + put("nwarhk", '\u2923'); + put("nwarr", '\u2196'); + put("nwArr", '\u21D6'); + put("nwarrow", '\u2196'); + put("nwnear", '\u2927'); + put("Oacute", '\u00D3'); + put("oacute", '\u00F3'); + put("oast", '\u229B'); + put("Ocirc", '\u00D4'); + put("ocirc", '\u00F4'); + put("ocir", '\u229A'); + put("Ocy", '\u041E'); + put("ocy", '\u043E'); + put("odash", '\u229D'); + put("Odblac", '\u0150'); + put("odblac", '\u0151'); + put("odiv", '\u2A38'); + put("odot", '\u2299'); + put("odsold", '\u29BC'); + put("OElig", '\u0152'); + put("oelig", '\u0153'); + put("ofcir", '\u29BF'); + put("Ofr", '\uD835', '\uDD12'); + put("ofr", '\uD835', '\uDD2C'); + put("ogon", '\u02DB'); + put("Ograve", '\u00D2'); + put("ograve", '\u00F2'); + put("ogt", '\u29C1'); + put("ohbar", '\u29B5'); + put("ohm", '\u03A9'); + put("oint", '\u222E'); + put("olarr", '\u21BA'); + put("olcir", '\u29BE'); + put("olcross", '\u29BB'); + put("oline", '\u203E'); + put("olt", '\u29C0'); + put("Omacr", '\u014C'); + put("omacr", '\u014D'); + put("Omega", '\u03A9'); + put("omega", '\u03C9'); + put("Omicron", '\u039F'); + put("omicron", '\u03BF'); + put("omid", '\u29B6'); + put("ominus", '\u2296'); + put("Oopf", '\uD835', '\uDD46'); + put("oopf", '\uD835', '\uDD60'); + put("opar", '\u29B7'); + put("OpenCurlyDoubleQuote", '\u201C'); + put("OpenCurlyQuote", '\u2018'); + put("operp", '\u29B9'); + put("oplus", '\u2295'); + put("orarr", '\u21BB'); + put("Or", '\u2A54'); + put("or", '\u2228'); + put("ord", '\u2A5D'); + put("order", '\u2134'); + put("orderof", '\u2134'); + put("ordf", '\u00AA'); + put("ordm", '\u00BA'); + put("origof", '\u22B6'); + put("oror", '\u2A56'); + put("orslope", '\u2A57'); + put("orv", '\u2A5B'); + put("oS", '\u24C8'); + put("Oscr", '\uD835', '\uDCAA'); + put("oscr", '\u2134'); + put("Oslash", '\u00D8'); + put("oslash", '\u00F8'); + put("osol", '\u2298'); + put("Otilde", '\u00D5'); + put("otilde", '\u00F5'); + put("otimesas", '\u2A36'); + put("Otimes", '\u2A37'); + put("otimes", '\u2297'); + put("Ouml", '\u00D6'); + put("ouml", '\u00F6'); + put("ovbar", '\u233D'); + put("OverBar", '\u203E'); + put("OverBrace", '\u23DE'); + put("OverBracket", '\u23B4'); + put("OverParenthesis", '\u23DC'); + put("para", '\u00B6'); + put("parallel", '\u2225'); + put("par", '\u2225'); + put("parsim", '\u2AF3'); + put("parsl", '\u2AFD'); + put("part", '\u2202'); + put("PartialD", '\u2202'); + put("Pcy", '\u041F'); + put("pcy", '\u043F'); + put("percnt", '\u0025'); + put("period", '\u002E'); + put("permil", '\u2030'); + put("perp", '\u22A5'); + put("pertenk", '\u2031'); + put("Pfr", '\uD835', '\uDD13'); + put("pfr", '\uD835', '\uDD2D'); + put("Phi", '\u03A6'); + put("phi", '\u03C6'); + put("phiv", '\u03D5'); + put("phmmat", '\u2133'); + put("phone", '\u260E'); + put("Pi", '\u03A0'); + put("pi", '\u03C0'); + put("pitchfork", '\u22D4'); + put("piv", '\u03D6'); + put("planck", '\u210F'); + put("planckh", '\u210E'); + put("plankv", '\u210F'); + put("plusacir", '\u2A23'); + put("plusb", '\u229E'); + put("pluscir", '\u2A22'); + put("plus", '\u002B'); + put("plusdo", '\u2214'); + put("plusdu", '\u2A25'); + put("pluse", '\u2A72'); + put("PlusMinus", '\u00B1'); + put("plusmn", '\u00B1'); + put("plussim", '\u2A26'); + put("plustwo", '\u2A27'); + put("pm", '\u00B1'); + put("Poincareplane", '\u210C'); + put("pointint", '\u2A15'); + put("popf", '\uD835', '\uDD61'); + put("Popf", '\u2119'); + put("pound", '\u00A3'); + put("prap", '\u2AB7'); + put("Pr", '\u2ABB'); + put("pr", '\u227A'); + put("prcue", '\u227C'); + put("precapprox", '\u2AB7'); + put("prec", '\u227A'); + put("preccurlyeq", '\u227C'); + put("Precedes", '\u227A'); + put("PrecedesEqual", '\u2AAF'); + put("PrecedesSlantEqual", '\u227C'); + put("PrecedesTilde", '\u227E'); + put("preceq", '\u2AAF'); + put("precnapprox", '\u2AB9'); + put("precneqq", '\u2AB5'); + put("precnsim", '\u22E8'); + put("pre", '\u2AAF'); + put("prE", '\u2AB3'); + put("precsim", '\u227E'); + put("prime", '\u2032'); + put("Prime", '\u2033'); + put("primes", '\u2119'); + put("prnap", '\u2AB9'); + put("prnE", '\u2AB5'); + put("prnsim", '\u22E8'); + put("prod", '\u220F'); + put("Product", '\u220F'); + put("profalar", '\u232E'); + put("profline", '\u2312'); + put("profsurf", '\u2313'); + put("prop", '\u221D'); + put("Proportional", '\u221D'); + put("Proportion", '\u2237'); + put("propto", '\u221D'); + put("prsim", '\u227E'); + put("prurel", '\u22B0'); + put("Pscr", '\uD835', '\uDCAB'); + put("pscr", '\uD835', '\uDCC5'); + put("Psi", '\u03A8'); + put("psi", '\u03C8'); + put("puncsp", '\u2008'); + put("Qfr", '\uD835', '\uDD14'); + put("qfr", '\uD835', '\uDD2E'); + put("qint", '\u2A0C'); + put("qopf", '\uD835', '\uDD62'); + put("Qopf", '\u211A'); + put("qprime", '\u2057'); + put("Qscr", '\uD835', '\uDCAC'); + put("qscr", '\uD835', '\uDCC6'); + put("quaternions", '\u210D'); + put("quatint", '\u2A16'); + put("quest", '\u003F'); + put("questeq", '\u225F'); + put("quot", '\"'); + put("QUOT", '\"'); + put("rAarr", '\u21DB'); + put("race", '\u223D', '\u0331'); + put("Racute", '\u0154'); + put("racute", '\u0155'); + put("radic", '\u221A'); + put("raemptyv", '\u29B3'); + put("rang", '\u27E9'); + put("Rang", '\u27EB'); + put("rangd", '\u2992'); + put("range", '\u29A5'); + put("rangle", '\u27E9'); + put("raquo", '\u00BB'); + put("rarrap", '\u2975'); + put("rarrb", '\u21E5'); + put("rarrbfs", '\u2920'); + put("rarrc", '\u2933'); + put("rarr", '\u2192'); + put("Rarr", '\u21A0'); + put("rArr", '\u21D2'); + put("rarrfs", '\u291E'); + put("rarrhk", '\u21AA'); + put("rarrlp", '\u21AC'); + put("rarrpl", '\u2945'); + put("rarrsim", '\u2974'); + put("Rarrtl", '\u2916'); + put("rarrtl", '\u21A3'); + put("rarrw", '\u219D'); + put("ratail", '\u291A'); + put("rAtail", '\u291C'); + put("ratio", '\u2236'); + put("rationals", '\u211A'); + put("rbarr", '\u290D'); + put("rBarr", '\u290F'); + put("RBarr", '\u2910'); + put("rbbrk", '\u2773'); + put("rbrace", '\u007D'); + put("rbrack", '\u005D'); + put("rbrke", '\u298C'); + put("rbrksld", '\u298E'); + put("rbrkslu", '\u2990'); + put("Rcaron", '\u0158'); + put("rcaron", '\u0159'); + put("Rcedil", '\u0156'); + put("rcedil", '\u0157'); + put("rceil", '\u2309'); + put("rcub", '\u007D'); + put("Rcy", '\u0420'); + put("rcy", '\u0440'); + put("rdca", '\u2937'); + put("rdldhar", '\u2969'); + put("rdquo", '\u201D'); + put("rdquor", '\u201D'); + put("rdsh", '\u21B3'); + put("real", '\u211C'); + put("realine", '\u211B'); + put("realpart", '\u211C'); + put("reals", '\u211D'); + put("Re", '\u211C'); + put("rect", '\u25AD'); + put("reg", '\u00AE'); + put("REG", '\u00AE'); + put("ReverseElement", '\u220B'); + put("ReverseEquilibrium", '\u21CB'); + put("ReverseUpEquilibrium", '\u296F'); + put("rfisht", '\u297D'); + put("rfloor", '\u230B'); + put("rfr", '\uD835', '\uDD2F'); + put("Rfr", '\u211C'); + put("rHar", '\u2964'); + put("rhard", '\u21C1'); + put("rharu", '\u21C0'); + put("rharul", '\u296C'); + put("Rho", '\u03A1'); + put("rho", '\u03C1'); + put("rhov", '\u03F1'); + put("RightAngleBracket", '\u27E9'); + put("RightArrowBar", '\u21E5'); + put("rightarrow", '\u2192'); + put("RightArrow", '\u2192'); + put("Rightarrow", '\u21D2'); + put("RightArrowLeftArrow", '\u21C4'); + put("rightarrowtail", '\u21A3'); + put("RightCeiling", '\u2309'); + put("RightDoubleBracket", '\u27E7'); + put("RightDownTeeVector", '\u295D'); + put("RightDownVectorBar", '\u2955'); + put("RightDownVector", '\u21C2'); + put("RightFloor", '\u230B'); + put("rightharpoondown", '\u21C1'); + put("rightharpoonup", '\u21C0'); + put("rightleftarrows", '\u21C4'); + put("rightleftharpoons", '\u21CC'); + put("rightrightarrows", '\u21C9'); + put("rightsquigarrow", '\u219D'); + put("RightTeeArrow", '\u21A6'); + put("RightTee", '\u22A2'); + put("RightTeeVector", '\u295B'); + put("rightthreetimes", '\u22CC'); + put("RightTriangleBar", '\u29D0'); + put("RightTriangle", '\u22B3'); + put("RightTriangleEqual", '\u22B5'); + put("RightUpDownVector", '\u294F'); + put("RightUpTeeVector", '\u295C'); + put("RightUpVectorBar", '\u2954'); + put("RightUpVector", '\u21BE'); + put("RightVectorBar", '\u2953'); + put("RightVector", '\u21C0'); + put("ring", '\u02DA'); + put("risingdotseq", '\u2253'); + put("rlarr", '\u21C4'); + put("rlhar", '\u21CC'); + put("rlm", '\u200F'); + put("rmoustache", '\u23B1'); + put("rmoust", '\u23B1'); + put("rnmid", '\u2AEE'); + put("roang", '\u27ED'); + put("roarr", '\u21FE'); + put("robrk", '\u27E7'); + put("ropar", '\u2986'); + put("ropf", '\uD835', '\uDD63'); + put("Ropf", '\u211D'); + put("roplus", '\u2A2E'); + put("rotimes", '\u2A35'); + put("RoundImplies", '\u2970'); + put("rpar", '\u0029'); + put("rpargt", '\u2994'); + put("rppolint", '\u2A12'); + put("rrarr", '\u21C9'); + put("Rrightarrow", '\u21DB'); + put("rsaquo", '\u203A'); + put("rscr", '\uD835', '\uDCC7'); + put("Rscr", '\u211B'); + put("rsh", '\u21B1'); + put("Rsh", '\u21B1'); + put("rsqb", '\u005D'); + put("rsquo", '\u2019'); + put("rsquor", '\u2019'); + put("rthree", '\u22CC'); + put("rtimes", '\u22CA'); + put("rtri", '\u25B9'); + put("rtrie", '\u22B5'); + put("rtrif", '\u25B8'); + put("rtriltri", '\u29CE'); + put("RuleDelayed", '\u29F4'); + put("ruluhar", '\u2968'); + put("rx", '\u211E'); + put("Sacute", '\u015A'); + put("sacute", '\u015B'); + put("sbquo", '\u201A'); + put("scap", '\u2AB8'); + put("Scaron", '\u0160'); + put("scaron", '\u0161'); + put("Sc", '\u2ABC'); + put("sc", '\u227B'); + put("sccue", '\u227D'); + put("sce", '\u2AB0'); + put("scE", '\u2AB4'); + put("Scedil", '\u015E'); + put("scedil", '\u015F'); + put("Scirc", '\u015C'); + put("scirc", '\u015D'); + put("scnap", '\u2ABA'); + put("scnE", '\u2AB6'); + put("scnsim", '\u22E9'); + put("scpolint", '\u2A13'); + put("scsim", '\u227F'); + put("Scy", '\u0421'); + put("scy", '\u0441'); + put("sdotb", '\u22A1'); + put("sdot", '\u22C5'); + put("sdote", '\u2A66'); + put("searhk", '\u2925'); + put("searr", '\u2198'); + put("seArr", '\u21D8'); + put("searrow", '\u2198'); + put("sect", '\u00A7'); + put("semi", '\u003B'); + put("seswar", '\u2929'); + put("setminus", '\u2216'); + put("setmn", '\u2216'); + put("sext", '\u2736'); + put("Sfr", '\uD835', '\uDD16'); + put("sfr", '\uD835', '\uDD30'); + put("sfrown", '\u2322'); + put("sharp", '\u266F'); + put("SHCHcy", '\u0429'); + put("shchcy", '\u0449'); + put("SHcy", '\u0428'); + put("shcy", '\u0448'); + put("ShortDownArrow", '\u2193'); + put("ShortLeftArrow", '\u2190'); + put("shortmid", '\u2223'); + put("shortparallel", '\u2225'); + put("ShortRightArrow", '\u2192'); + put("ShortUpArrow", '\u2191'); + put("shy", '\u00AD'); + put("Sigma", '\u03A3'); + put("sigma", '\u03C3'); + put("sigmaf", '\u03C2'); + put("sigmav", '\u03C2'); + put("sim", '\u223C'); + put("simdot", '\u2A6A'); + put("sime", '\u2243'); + put("simeq", '\u2243'); + put("simg", '\u2A9E'); + put("simgE", '\u2AA0'); + put("siml", '\u2A9D'); + put("simlE", '\u2A9F'); + put("simne", '\u2246'); + put("simplus", '\u2A24'); + put("simrarr", '\u2972'); + put("slarr", '\u2190'); + put("SmallCircle", '\u2218'); + put("smallsetminus", '\u2216'); + put("smashp", '\u2A33'); + put("smeparsl", '\u29E4'); + put("smid", '\u2223'); + put("smile", '\u2323'); + put("smt", '\u2AAA'); + put("smte", '\u2AAC'); + put("smtes", '\u2AAC', '\uFE00'); + put("SOFTcy", '\u042C'); + put("softcy", '\u044C'); + put("solbar", '\u233F'); + put("solb", '\u29C4'); + put("sol", '\u002F'); + put("Sopf", '\uD835', '\uDD4A'); + put("sopf", '\uD835', '\uDD64'); + put("spades", '\u2660'); + put("spadesuit", '\u2660'); + put("spar", '\u2225'); + put("sqcap", '\u2293'); + put("sqcaps", '\u2293', '\uFE00'); + put("sqcup", '\u2294'); + put("sqcups", '\u2294', '\uFE00'); + put("Sqrt", '\u221A'); + put("sqsub", '\u228F'); + put("sqsube", '\u2291'); + put("sqsubset", '\u228F'); + put("sqsubseteq", '\u2291'); + put("sqsup", '\u2290'); + put("sqsupe", '\u2292'); + put("sqsupset", '\u2290'); + put("sqsupseteq", '\u2292'); + put("square", '\u25A1'); + put("Square", '\u25A1'); + put("SquareIntersection", '\u2293'); + put("SquareSubset", '\u228F'); + put("SquareSubsetEqual", '\u2291'); + put("SquareSuperset", '\u2290'); + put("SquareSupersetEqual", '\u2292'); + put("SquareUnion", '\u2294'); + put("squarf", '\u25AA'); + put("squ", '\u25A1'); + put("squf", '\u25AA'); + put("srarr", '\u2192'); + put("Sscr", '\uD835', '\uDCAE'); + put("sscr", '\uD835', '\uDCC8'); + put("ssetmn", '\u2216'); + put("ssmile", '\u2323'); + put("sstarf", '\u22C6'); + put("Star", '\u22C6'); + put("star", '\u2606'); + put("starf", '\u2605'); + put("straightepsilon", '\u03F5'); + put("straightphi", '\u03D5'); + put("strns", '\u00AF'); + put("sub", '\u2282'); + put("Sub", '\u22D0'); + put("subdot", '\u2ABD'); + put("subE", '\u2AC5'); + put("sube", '\u2286'); + put("subedot", '\u2AC3'); + put("submult", '\u2AC1'); + put("subnE", '\u2ACB'); + put("subne", '\u228A'); + put("subplus", '\u2ABF'); + put("subrarr", '\u2979'); + put("subset", '\u2282'); + put("Subset", '\u22D0'); + put("subseteq", '\u2286'); + put("subseteqq", '\u2AC5'); + put("SubsetEqual", '\u2286'); + put("subsetneq", '\u228A'); + put("subsetneqq", '\u2ACB'); + put("subsim", '\u2AC7'); + put("subsub", '\u2AD5'); + put("subsup", '\u2AD3'); + put("succapprox", '\u2AB8'); + put("succ", '\u227B'); + put("succcurlyeq", '\u227D'); + put("Succeeds", '\u227B'); + put("SucceedsEqual", '\u2AB0'); + put("SucceedsSlantEqual", '\u227D'); + put("SucceedsTilde", '\u227F'); + put("succeq", '\u2AB0'); + put("succnapprox", '\u2ABA'); + put("succneqq", '\u2AB6'); + put("succnsim", '\u22E9'); + put("succsim", '\u227F'); + put("SuchThat", '\u220B'); + put("sum", '\u2211'); + put("Sum", '\u2211'); + put("sung", '\u266A'); + put("sup1", '\u00B9'); + put("sup2", '\u00B2'); + put("sup3", '\u00B3'); + put("sup", '\u2283'); + put("Sup", '\u22D1'); + put("supdot", '\u2ABE'); + put("supdsub", '\u2AD8'); + put("supE", '\u2AC6'); + put("supe", '\u2287'); + put("supedot", '\u2AC4'); + put("Superset", '\u2283'); + put("SupersetEqual", '\u2287'); + put("suphsol", '\u27C9'); + put("suphsub", '\u2AD7'); + put("suplarr", '\u297B'); + put("supmult", '\u2AC2'); + put("supnE", '\u2ACC'); + put("supne", '\u228B'); + put("supplus", '\u2AC0'); + put("supset", '\u2283'); + put("Supset", '\u22D1'); + put("supseteq", '\u2287'); + put("supseteqq", '\u2AC6'); + put("supsetneq", '\u228B'); + put("supsetneqq", '\u2ACC'); + put("supsim", '\u2AC8'); + put("supsub", '\u2AD4'); + put("supsup", '\u2AD6'); + put("swarhk", '\u2926'); + put("swarr", '\u2199'); + put("swArr", '\u21D9'); + put("swarrow", '\u2199'); + put("swnwar", '\u292A'); + put("szlig", '\u00DF'); + put("Tab", '\u0009'); + put("target", '\u2316'); + put("Tau", '\u03A4'); + put("tau", '\u03C4'); + put("tbrk", '\u23B4'); + put("Tcaron", '\u0164'); + put("tcaron", '\u0165'); + put("Tcedil", '\u0162'); + put("tcedil", '\u0163'); + put("Tcy", '\u0422'); + put("tcy", '\u0442'); + put("tdot", '\u20DB'); + put("telrec", '\u2315'); + put("Tfr", '\uD835', '\uDD17'); + put("tfr", '\uD835', '\uDD31'); + put("there4", '\u2234'); + put("therefore", '\u2234'); + put("Therefore", '\u2234'); + put("Theta", '\u0398'); + put("theta", '\u03B8'); + put("thetasym", '\u03D1'); + put("thetav", '\u03D1'); + put("thickapprox", '\u2248'); + put("thicksim", '\u223C'); + put("ThickSpace", '\u205F', '\u200A'); + put("ThinSpace", '\u2009'); + put("thinsp", '\u2009'); + put("thkap", '\u2248'); + put("thksim", '\u223C'); + put("THORN", '\u00DE'); + put("thorn", '\u00FE'); + put("tilde", '\u02DC'); + put("Tilde", '\u223C'); + put("TildeEqual", '\u2243'); + put("TildeFullEqual", '\u2245'); + put("TildeTilde", '\u2248'); + put("timesbar", '\u2A31'); + put("timesb", '\u22A0'); + put("times", '\u00D7'); + put("timesd", '\u2A30'); + put("tint", '\u222D'); + put("toea", '\u2928'); + put("topbot", '\u2336'); + put("topcir", '\u2AF1'); + put("top", '\u22A4'); + put("Topf", '\uD835', '\uDD4B'); + put("topf", '\uD835', '\uDD65'); + put("topfork", '\u2ADA'); + put("tosa", '\u2929'); + put("tprime", '\u2034'); + put("trade", '\u2122'); + put("TRADE", '\u2122'); + put("triangle", '\u25B5'); + put("triangledown", '\u25BF'); + put("triangleleft", '\u25C3'); + put("trianglelefteq", '\u22B4'); + put("triangleq", '\u225C'); + put("triangleright", '\u25B9'); + put("trianglerighteq", '\u22B5'); + put("tridot", '\u25EC'); + put("trie", '\u225C'); + put("triminus", '\u2A3A'); + put("TripleDot", '\u20DB'); + put("triplus", '\u2A39'); + put("trisb", '\u29CD'); + put("tritime", '\u2A3B'); + put("trpezium", '\u23E2'); + put("Tscr", '\uD835', '\uDCAF'); + put("tscr", '\uD835', '\uDCC9'); + put("TScy", '\u0426'); + put("tscy", '\u0446'); + put("TSHcy", '\u040B'); + put("tshcy", '\u045B'); + put("Tstrok", '\u0166'); + put("tstrok", '\u0167'); + put("twixt", '\u226C'); + put("twoheadleftarrow", '\u219E'); + put("twoheadrightarrow", '\u21A0'); + put("Uacute", '\u00DA'); + put("uacute", '\u00FA'); + put("uarr", '\u2191'); + put("Uarr", '\u219F'); + put("uArr", '\u21D1'); + put("Uarrocir", '\u2949'); + put("Ubrcy", '\u040E'); + put("ubrcy", '\u045E'); + put("Ubreve", '\u016C'); + put("ubreve", '\u016D'); + put("Ucirc", '\u00DB'); + put("ucirc", '\u00FB'); + put("Ucy", '\u0423'); + put("ucy", '\u0443'); + put("udarr", '\u21C5'); + put("Udblac", '\u0170'); + put("udblac", '\u0171'); + put("udhar", '\u296E'); + put("ufisht", '\u297E'); + put("Ufr", '\uD835', '\uDD18'); + put("ufr", '\uD835', '\uDD32'); + put("Ugrave", '\u00D9'); + put("ugrave", '\u00F9'); + put("uHar", '\u2963'); + put("uharl", '\u21BF'); + put("uharr", '\u21BE'); + put("uhblk", '\u2580'); + put("ulcorn", '\u231C'); + put("ulcorner", '\u231C'); + put("ulcrop", '\u230F'); + put("ultri", '\u25F8'); + put("Umacr", '\u016A'); + put("umacr", '\u016B'); + put("uml", '\u00A8'); + put("UnderBar", '\u005F'); + put("UnderBrace", '\u23DF'); + put("UnderBracket", '\u23B5'); + put("UnderParenthesis", '\u23DD'); + put("Union", '\u22C3'); + put("UnionPlus", '\u228E'); + put("Uogon", '\u0172'); + put("uogon", '\u0173'); + put("Uopf", '\uD835', '\uDD4C'); + put("uopf", '\uD835', '\uDD66'); + put("UpArrowBar", '\u2912'); + put("uparrow", '\u2191'); + put("UpArrow", '\u2191'); + put("Uparrow", '\u21D1'); + put("UpArrowDownArrow", '\u21C5'); + put("updownarrow", '\u2195'); + put("UpDownArrow", '\u2195'); + put("Updownarrow", '\u21D5'); + put("UpEquilibrium", '\u296E'); + put("upharpoonleft", '\u21BF'); + put("upharpoonright", '\u21BE'); + put("uplus", '\u228E'); + put("UpperLeftArrow", '\u2196'); + put("UpperRightArrow", '\u2197'); + put("upsi", '\u03C5'); + put("Upsi", '\u03D2'); + put("upsih", '\u03D2'); + put("Upsilon", '\u03A5'); + put("upsilon", '\u03C5'); + put("UpTeeArrow", '\u21A5'); + put("UpTee", '\u22A5'); + put("upuparrows", '\u21C8'); + put("urcorn", '\u231D'); + put("urcorner", '\u231D'); + put("urcrop", '\u230E'); + put("Uring", '\u016E'); + put("uring", '\u016F'); + put("urtri", '\u25F9'); + put("Uscr", '\uD835', '\uDCB0'); + put("uscr", '\uD835', '\uDCCA'); + put("utdot", '\u22F0'); + put("Utilde", '\u0168'); + put("utilde", '\u0169'); + put("utri", '\u25B5'); + put("utrif", '\u25B4'); + put("uuarr", '\u21C8'); + put("Uuml", '\u00DC'); + put("uuml", '\u00FC'); + put("uwangle", '\u29A7'); + put("vangrt", '\u299C'); + put("varepsilon", '\u03F5'); + put("varkappa", '\u03F0'); + put("varnothing", '\u2205'); + put("varphi", '\u03D5'); + put("varpi", '\u03D6'); + put("varpropto", '\u221D'); + put("varr", '\u2195'); + put("vArr", '\u21D5'); + put("varrho", '\u03F1'); + put("varsigma", '\u03C2'); + put("varsubsetneq", '\u228A', '\uFE00'); + put("varsubsetneqq", '\u2ACB', '\uFE00'); + put("varsupsetneq", '\u228B', '\uFE00'); + put("varsupsetneqq", '\u2ACC', '\uFE00'); + put("vartheta", '\u03D1'); + put("vartriangleleft", '\u22B2'); + put("vartriangleright", '\u22B3'); + put("vBar", '\u2AE8'); + put("Vbar", '\u2AEB'); + put("vBarv", '\u2AE9'); + put("Vcy", '\u0412'); + put("vcy", '\u0432'); + put("vdash", '\u22A2'); + put("vDash", '\u22A8'); + put("Vdash", '\u22A9'); + put("VDash", '\u22AB'); + put("Vdashl", '\u2AE6'); + put("veebar", '\u22BB'); + put("vee", '\u2228'); + put("Vee", '\u22C1'); + put("veeeq", '\u225A'); + put("vellip", '\u22EE'); + put("verbar", '\u007C'); + put("Verbar", '\u2016'); + put("vert", '\u007C'); + put("Vert", '\u2016'); + put("VerticalBar", '\u2223'); + put("VerticalLine", '\u007C'); + put("VerticalSeparator", '\u2758'); + put("VerticalTilde", '\u2240'); + put("VeryThinSpace", '\u200A'); + put("Vfr", '\uD835', '\uDD19'); + put("vfr", '\uD835', '\uDD33'); + put("vltri", '\u22B2'); + put("vnsub", '\u2282', '\u20D2'); + put("vnsup", '\u2283', '\u20D2'); + put("Vopf", '\uD835', '\uDD4D'); + put("vopf", '\uD835', '\uDD67'); + put("vprop", '\u221D'); + put("vrtri", '\u22B3'); + put("Vscr", '\uD835', '\uDCB1'); + put("vscr", '\uD835', '\uDCCB'); + put("vsubnE", '\u2ACB', '\uFE00'); + put("vsubne", '\u228A', '\uFE00'); + put("vsupnE", '\u2ACC', '\uFE00'); + put("vsupne", '\u228B', '\uFE00'); + put("Vvdash", '\u22AA'); + put("vzigzag", '\u299A'); + put("Wcirc", '\u0174'); + put("wcirc", '\u0175'); + put("wedbar", '\u2A5F'); + put("wedge", '\u2227'); + put("Wedge", '\u22C0'); + put("wedgeq", '\u2259'); + put("weierp", '\u2118'); + put("Wfr", '\uD835', '\uDD1A'); + put("wfr", '\uD835', '\uDD34'); + put("Wopf", '\uD835', '\uDD4E'); + put("wopf", '\uD835', '\uDD68'); + put("wp", '\u2118'); + put("wr", '\u2240'); + put("wreath", '\u2240'); + put("Wscr", '\uD835', '\uDCB2'); + put("wscr", '\uD835', '\uDCCC'); + put("xcap", '\u22C2'); + put("xcirc", '\u25EF'); + put("xcup", '\u22C3'); + put("xdtri", '\u25BD'); + put("Xfr", '\uD835', '\uDD1B'); + put("xfr", '\uD835', '\uDD35'); + put("xharr", '\u27F7'); + put("xhArr", '\u27FA'); + put("Xi", '\u039E'); + put("xi", '\u03BE'); + put("xlarr", '\u27F5'); + put("xlArr", '\u27F8'); + put("xmap", '\u27FC'); + put("xnis", '\u22FB'); + put("xodot", '\u2A00'); + put("Xopf", '\uD835', '\uDD4F'); + put("xopf", '\uD835', '\uDD69'); + put("xoplus", '\u2A01'); + put("xotime", '\u2A02'); + put("xrarr", '\u27F6'); + put("xrArr", '\u27F9'); + put("Xscr", '\uD835', '\uDCB3'); + put("xscr", '\uD835', '\uDCCD'); + put("xsqcup", '\u2A06'); + put("xuplus", '\u2A04'); + put("xutri", '\u25B3'); + put("xvee", '\u22C1'); + put("xwedge", '\u22C0'); + put("Yacute", '\u00DD'); + put("yacute", '\u00FD'); + put("YAcy", '\u042F'); + put("yacy", '\u044F'); + put("Ycirc", '\u0176'); + put("ycirc", '\u0177'); + put("Ycy", '\u042B'); + put("ycy", '\u044B'); + put("yen", '\u00A5'); + put("Yfr", '\uD835', '\uDD1C'); + put("yfr", '\uD835', '\uDD36'); + put("YIcy", '\u0407'); + put("yicy", '\u0457'); + put("Yopf", '\uD835', '\uDD50'); + put("yopf", '\uD835', '\uDD6A'); + put("Yscr", '\uD835', '\uDCB4'); + put("yscr", '\uD835', '\uDCCE'); + put("YUcy", '\u042E'); + put("yucy", '\u044E'); + put("yuml", '\u00FF'); + put("Yuml", '\u0178'); + put("Zacute", '\u0179'); + put("zacute", '\u017A'); + put("Zcaron", '\u017D'); + put("zcaron", '\u017E'); + put("Zcy", '\u0417'); + put("zcy", '\u0437'); + put("Zdot", '\u017B'); + put("zdot", '\u017C'); + put("zeetrf", '\u2128'); + put("ZeroWidthSpace", '\u200B'); + put("Zeta", '\u0396'); + put("zeta", '\u03B6'); + put("zfr", '\uD835', '\uDD37'); + put("Zfr", '\u2128'); + put("ZHcy", '\u0416'); + put("zhcy", '\u0436'); + put("zigrarr", '\u21DD'); + put("zopf", '\uD835', '\uDD6B'); + put("Zopf", '\u2124'); + put("Zscr", '\uD835', '\uDCB5'); + put("zscr", '\uD835', '\uDCCF'); + put("zwj", '\u200D'); + put("zwnj", '\u200C'); + } + + private static void put(String name, char c) { + entities.put(name, String.valueOf(c)); + } + + private static void put(String name, char c1, char c2) { + entities.put(name, String.valueOf(new char[] { c1, c2 })); + } + + static String getCharacters(EntityTree tree) { + String name = tree.getName().toString(); + if (name.startsWith("#")) { + try { + int v = StringUtils.toLowerCase(name).startsWith("#x") + ? Integer.parseInt(name.substring(2), 16) + : Integer.parseInt(name.substring(1), 10); + // See https://www.w3.org/TR/html52/syntax.html#character-references + if (Character.isDefined(v) + && (!Character.isISOControl(v) || Character.isSpaceChar(v)) + && (v < 0xd800 || v > 0xdfff)) { + return String.valueOf((char) v); + } + } catch (NumberFormatException ex) { + //ignore + } + return null; + } else { + return entities.get(name); + } + } +} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java index e656e4e9e0d..4a1c0702e06 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -59,6 +59,7 @@ import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.EntityTree; import com.sun.source.tree.CatchTree; import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; @@ -102,7 +103,6 @@ import com.sun.tools.javac.parser.DocCommentParser; import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.parser.Tokens.Comment; -import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Notes; @@ -1162,6 +1162,11 @@ public void setBreakIterator(BreakIterator breakiterator) { this.breakIterator = breakiterator; } + @Override @DefinedBy(Api.COMPILER_TREE) + public String getCharacters(EntityTree tree) { + return Entity.getCharacters(tree); + } + /** * Makes a copy of a tree, noting the value resulting from copying a particular leaf. **/ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java index f43484bb3b1..aebbc78da36 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java @@ -220,7 +220,11 @@ public static EnumSet<Flag> asFlagSet(long flags) { */ public static final long UNION = 1L<<39; - // Flag bit (1L << 40) is available. + /** + * Flags an erroneous TypeSymbol as viable for recovery. + * TypeSymbols only. + */ + public static final long RECOVERABLE = 1L<<40; /** * Flag that marks an 'effectively final' local variable. @@ -508,6 +512,7 @@ public enum Flag { MATCH_BINDING(Flags.MATCH_BINDING), MATCH_BINDING_TO_OUTER(Flags.MATCH_BINDING_TO_OUTER), RECORD(Flags.RECORD), + RECOVERABLE(Flags.RECOVERABLE), SEALED(Flags.SEALED), NON_SEALED(Flags.NON_SEALED) { @Override diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index d79f3f7b51a..cf760027c67 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -166,6 +166,7 @@ public boolean isEnabled() { */ public boolean isPreview(Feature feature) { if (feature == Feature.PATTERN_MATCHING_IN_INSTANCEOF || + feature == Feature.DECONSTRUCTION_PATTERNS || feature == Feature.REIFIABLE_TYPES_INSTANCEOF || feature == Feature.RECORDS || feature == Feature.SEALED_CLASSES) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java index 72e92107bb7..773333de1e2 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java @@ -218,6 +218,9 @@ public enum Feature { REIFIABLE_TYPES_INSTANCEOF(JDK16, Fragments.FeatureReifiableTypesInstanceof, DiagKind.PLURAL), RECORDS(JDK16, Fragments.FeatureRecords, DiagKind.PLURAL), SEALED_CLASSES(JDK16, Fragments.FeatureSealedClasses, DiagKind.PLURAL), + LAMBDA_PARAMETER_SHADOWING(JDK16), + UNDERSCORE_AS_PARAM_NAME(JDK16), + DECONSTRUCTION_PATTERNS(JDK16, Fragments.FeatureDeconstructionPatterns, DiagKind.PLURAL), ; enum DiagKind { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java index 5a5d78be3c8..15ab9cf5642 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java @@ -155,6 +155,14 @@ public static Symtab instance(Context context) { /** The builtin type of all methods. */ public final ClassSymbol methodClass; + /** A common method type for all those method symbols owning a lambda scope. + */ + public final MethodType lambdaScopeMethodType; + + /** A common method type for all those method symbols owning a block scope. + */ + public final MethodType blockScopeMethodType; + /** A symbol for the java.base module. */ public final ModuleSymbol java_base; @@ -479,6 +487,9 @@ public <R, P> R accept(ElementVisitor<R, P> v, P p) { methodClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Method, noSymbol); methodClass.members_field = new Scope.ErrorScope(boundClass); + lambdaScopeMethodType = new MethodType(List.nil(), voidType, List.nil(), methodClass); + blockScopeMethodType = new MethodType(List.nil(), voidType, List.nil(), methodClass); + // Create class to hold all predefined constants and operations. predefClass = new ClassSymbol(PUBLIC|ACYCLIC, names.empty, rootPackage); WriteableScope scope = WriteableScope.create(predefClass); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index cf26504dfa9..450a63902cc 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -27,7 +27,7 @@ import java.util.*; import java.util.function.BiConsumer; -import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.lang.model.element.ElementKind; import javax.tools.JavaFileObject; @@ -120,6 +120,7 @@ public class Attr extends JCTree.Visitor { final Annotate annotate; final ArgumentAttr argumentAttr; final MatchBindingsComputer matchBindingsComputer; + final AttrRecover attrRecover; public static Attr instance(Context context) { Attr instance = context.get(attrKey); @@ -157,6 +158,7 @@ protected Attr(Context context) { dependencies = Dependencies.instance(context); argumentAttr = ArgumentAttr.instance(context); matchBindingsComputer = MatchBindingsComputer.instance(context); + attrRecover = AttrRecover.instance(context); Options options = Options.instance(context); @@ -166,6 +168,7 @@ protected Attr(Context context) { allowLambda = Feature.LAMBDA.allowedInSource(source); allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source); allowStaticInterfaceMethods = Feature.STATIC_INTERFACE_METHODS.allowedInSource(source); + allowShadowingOfLambdaParameters = Feature.LAMBDA_PARAMETER_SHADOWING.allowedInSource(source); allowReifiableTypesInInstanceof = Feature.REIFIABLE_TYPES_INSTANCEOF.allowedInSource(source) && (!preview.isPreview(Feature.REIFIABLE_TYPES_INSTANCEOF) || preview.isEnabled()); @@ -211,6 +214,11 @@ protected Attr(Context context) { */ boolean useBeforeDeclarationWarning; + /** + * Switch: allow shadowing of lambda parameters? + */ + boolean allowShadowingOfLambdaParameters; + /** * Switch: name of source level; used for error reporting. */ @@ -419,8 +427,9 @@ private Env<AttrContext> attribToTree(JCTree root, Env<AttrContext> env, JCTree JavaFileObject prev = log.useSource(env.toplevel.sourcefile); try { deferredAttr.attribSpeculative(root, env, resultInfo, - null, DeferredAttr.AttributionMode.ANALYZER, + null, DeferredAttr.AttributionMode.ATTRIB_TO_TREE, argumentAttr.withLocalCacheContext()); + attrRecover.doRecovery(); } catch (BreakAttr b) { return b.env; } catch (AssertionError ae) { @@ -738,6 +747,7 @@ public Type attribStat(JCTree tree, Env<AttrContext> env) { Env<AttrContext> analyzeEnv = analyzer.copyEnvIfNeeded(tree, env); Type result = attribTree(tree, env, statInfo); analyzer.analyzeIfNeeded(tree, analyzeEnv); + attrRecover.doRecovery(); return result; } @@ -1309,6 +1319,12 @@ public void visitVarDef(JCVariableDecl tree) { } } result = tree.type = v.type; + if (tree.name == names.underscore) { + WriteableScope enclScope = enter.enterScope(env); + if (enclScope != null) { + enclScope.remove(tree.sym); + } + } if (env.enclClass.sym.isRecord() && tree.sym.owner.kind == TYP && !v.isStatic()) { if (isNonArgsMethodInObject(v.name)) { log.error(tree, Errors.IllegalRecordComponentName(v)); @@ -1405,7 +1421,7 @@ public void visitBlock(JCBlock tree) { // created BLOCK-method. Symbol fakeOwner = new MethodSymbol(tree.flags | BLOCK | - env.info.scope.owner.flags() & STRICTFP, names.empty, null, + env.info.scope.owner.flags() & STRICTFP, names.empty, syms.blockScopeMethodType, env.info.scope.owner); final Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dupUnshared(fakeOwner))); @@ -2092,6 +2108,7 @@ public void visitIf(JCIf tree) { } void preFlow(JCTree tree) { + attrRecover.doRecovery(); new PostAttrAnalyzer() { @Override public void scan(JCTree tree) { @@ -3114,6 +3131,7 @@ TargetInfo getTargetInfo(JCPolyExpression that, ResultInfo resultInfo, List<Type } void preFlow(JCLambda tree) { + attrRecover.doRecovery(); new PostAttrAnalyzer() { @Override public void scan(JCTree tree) { @@ -3324,10 +3342,11 @@ public MethodSymbol removeClinit(ClassSymbol sym) { public Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) { Env<AttrContext> lambdaEnv; Symbol owner = env.info.scope.owner; + ClassSymbol enclClass = owner.enclClass(); + Symbol newScopeOwner = null; if (owner.kind == VAR && owner.owner.kind == TYP) { //field initializer - ClassSymbol enclClass = owner.enclClass(); - Symbol newScopeOwner = env.info.scope.owner; + newScopeOwner = env.info.scope.owner; /* if the field isn't static, then we can get the first constructor * and use it as the owner of the environment. This is what * LTM code is doing to look for type annotations so we are fine. @@ -3352,6 +3371,16 @@ public Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) { } newScopeOwner = clinit; } + } else { + if (allowShadowingOfLambdaParameters) { + newScopeOwner = new MethodSymbol( + HYPOTHETICAL, + names.empty, + syms.lambdaScopeMethodType, + owner); + } + } + if (newScopeOwner != null) { lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared(newScopeOwner))); } else { lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup())); @@ -3922,16 +3951,7 @@ public void visitTypeTest(JCInstanceOf tree) { if (preview.isPreview(Feature.REIFIABLE_TYPES_INSTANCEOF)) { preview.warnPreview(tree.expr.pos(), Feature.REIFIABLE_TYPES_INSTANCEOF); } - Warner warner = new Warner(); - if (!types.isCastable(exprtype, clazztype, warner)) { - chk.basicHandler.report(tree.expr.pos(), - diags.fragment(Fragments.InconvertibleTypes(exprtype, clazztype))); - } else if (warner.hasLint(LintCategory.UNCHECKED)) { - log.error(tree.expr.pos(), - Errors.InstanceofReifiableNotSafe(exprtype, clazztype)); - } else { - valid = true; - } + valid = verifyCastable(tree.expr.pos(), exprtype, clazztype); } else { log.error(typeTree.pos(), Errors.IllegalGenericTypeForInstof); } @@ -3945,18 +3965,79 @@ public void visitTypeTest(JCInstanceOf tree) { } public void visitBindingPattern(JCBindingPattern tree) { - ResultInfo varInfo = new ResultInfo(KindSelector.TYP, resultInfo.pt, resultInfo.checkContext); - tree.type = attribTree(tree.vartype, env, varInfo); - VarSymbol v = tree.symbol = new BindingSymbol(tree.name, tree.vartype.type, env.info.scope.owner); + if (tree.vartype != null) { + ResultInfo varInfo = new ResultInfo(KindSelector.TYP, resultInfo.pt, resultInfo.checkContext); + tree.type = attribTree(tree.vartype, env, varInfo); + } else { + tree.type = resultInfo.pt; + } + VarSymbol v = tree.symbol = new BindingSymbol(tree.name, tree.vartype != null ? tree.vartype.type : (tree.type.hasTag(BOT) ? syms.objectType : tree.type), env.info.scope.owner); if (chk.checkUnique(tree.pos(), v, env.info.scope)) { chk.checkTransparentVar(tree.pos(), v, env.info.scope); } - annotate.queueScanTreeAndTypeAnnotate(tree.vartype, env, v, tree.pos()); - annotate.flush(); + if (tree.vartype != null) { + annotate.queueScanTreeAndTypeAnnotate(tree.vartype, env, v, tree.pos()); + annotate.flush(); + } result = tree.type; matchBindings = new MatchBindings(List.of(tree.symbol), List.nil()); } + @Override + public void visitDeconstructionPattern(JCDeconstructionPattern tree) { + tree.type = attribType(tree.deconstructor, env); + Type site = types.removeWildcards(tree.type); + List<Type> expectedRecordTypes; + if (site.tsym.kind == Kind.TYP && ((ClassSymbol) site.tsym).isRecord()) { + ClassSymbol record = (ClassSymbol) site.tsym; + expectedRecordTypes = record.getRecordComponents().stream().map(rc -> types.memberType(site, rc)).collect(List.collector()); + tree.record = record; + } else { + log.error(tree.pos(), Errors.DeconstructionPatternOnlyRecords(site.tsym)); + expectedRecordTypes = Stream.generate(() -> Type.noType) + .limit(tree.nested.size()) + .collect(List.collector()); + } + ListBuffer<BindingSymbol> outBindings = new ListBuffer<>(); + List<Type> recordTypes = expectedRecordTypes; + List<JCPattern> nestedPatterns = tree.nested; + while (recordTypes.nonEmpty() && nestedPatterns.nonEmpty()) { + boolean nestedIsVarPattern = nestedPatterns.head.hasTag(BINDINGPATTERN) && + ((JCBindingPattern) nestedPatterns.head).vartype == null; + attribExpr(nestedPatterns.head, env, nestedIsVarPattern ? recordTypes.head : Type.noType); + verifyCastable(nestedPatterns.head.pos(), recordTypes.head, nestedPatterns.head.type); + outBindings.addAll(matchBindings.bindingsWhenTrue); + nestedPatterns = nestedPatterns.tail; + recordTypes = recordTypes.tail; + } + if (recordTypes.nonEmpty() || nestedPatterns.nonEmpty()) { + while (nestedPatterns.nonEmpty()) { + attribExpr(nestedPatterns.head, env, Type.noType); + nestedPatterns = nestedPatterns.tail; + } + List<Type> nestedTypes = + tree.nested.stream().map(p -> p.type).collect(List.collector()); + log.error(tree.pos(), + Errors.IncorrectNumberOfNestedPatterns(expectedRecordTypes, + nestedTypes)); + } + result = tree.type; + matchBindings = new MatchBindings(outBindings.toList(), List.nil()); + } + + private boolean verifyCastable(DiagnosticPosition pos, Type exprtype, Type clazztype) { + Warner warner = new Warner(); + if (!chk.checkCastable(pos, exprtype, clazztype, chk.basicHandler, warner)) { + return false; + } else if (warner.hasLint(LintCategory.UNCHECKED)) { + log.error(pos, + Errors.InstanceofReifiableNotSafe(exprtype, clazztype)); + return false; + } else { + return true; + } + } + public void visitIndexed(JCArrayAccess tree) { Type owntype = types.createErrorType(tree.type); Type atype = attribExpr(tree.indexed, env); @@ -4307,10 +4388,7 @@ Type checkMethodIdInternal(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { if (resultInfo.pkind.contains(KindSelector.POLY)) { - Type pt = resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase)); - Type owntype = checkIdInternal(tree, site, sym, pt, env, resultInfo); - resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); - return owntype; + return attrRecover.recoverMethodInvocation(tree, site, sym, env, resultInfo); } else { return checkIdInternal(tree, site, sym, resultInfo.pt, env, resultInfo); } @@ -4916,9 +4994,12 @@ public void visitAnnotatedType(JCAnnotatedType tree) { } public void visitErroneous(JCErroneous tree) { - if (tree.errs != null) + if (tree.errs != null) { + Env<AttrContext> errEnv = env.dup(env.tree); + errEnv.info.returnResult = unknownExprInfo; for (JCTree err : tree.errs) - attribTree(err, env, new ResultInfo(KindSelector.ERR, pt())); + attribTree(err, errEnv, new ResultInfo(KindSelector.ERR, pt())); + } result = tree.type = syms.errType; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrRecover.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrRecover.java new file mode 100644 index 00000000000..8fd09501717 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrRecover.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.tools.javac.comp; + +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.TypeSymbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.ArrayType; +import com.sun.tools.javac.code.Type.ErrorType; +import com.sun.tools.javac.code.TypeTag; +import com.sun.tools.javac.code.Types; +import com.sun.tools.javac.comp.Attr.ResultInfo; +import com.sun.tools.javac.comp.DeferredAttr.AttrMode; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCErroneous; +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCLambda; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.JCTree.JCReturn; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.JCTree.Tag; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeTranslator; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Names; + +/** This is an error recovery addon for Attr. Currently, it recovers + * method invocations with lambdas, that require type inference. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class AttrRecover { + protected static final Context.Key<AttrRecover> attrRepairKey = new Context.Key<>(); + + final Attr attr; + final DeferredAttr deferredAttr; + final Names names; + final TreeMaker make; + final Symtab syms; + final Types types; + + public static AttrRecover instance(Context context) { + AttrRecover instance = context.get(attrRepairKey); + if (instance == null) + instance = new AttrRecover(context); + return instance; + } + + protected AttrRecover(Context context) { + context.put(attrRepairKey, this); + + attr = Attr.instance(context); + deferredAttr = DeferredAttr.instance(context); + names = Names.instance(context); + make = TreeMaker.instance(context); + syms = Symtab.instance(context); + types = Types.instance(context); + } + + private final ListBuffer<RecoverTodo> recoveryTodo = new ListBuffer<>(); + + public void doRecovery() { + while (recoveryTodo.nonEmpty()) { + RecoverTodo todo = recoveryTodo.remove(); + ListBuffer<Runnable> rollback = new ListBuffer<>(); + boolean repaired = false; + RECOVER: if (todo.env.tree.hasTag(Tag.APPLY)) { + JCMethodInvocation mit = (JCMethodInvocation) todo.env.tree; + boolean vararg = (todo.candSym.flags() & Flags.VARARGS) != 0; + if (!vararg && + mit.args.length() > todo.candSym.type.getParameterTypes().length()) { + break RECOVER; //too many actual parameters, skip + } + List<JCExpression> args = mit.args; + List<Type> formals = todo.candSym.type.getParameterTypes(); + while (args.nonEmpty() && formals.nonEmpty()) { + JCExpression arg = args.head; + Type formal = formals.tail.nonEmpty() || !vararg + ? formals.head : ((ArrayType) formals.head).elemtype; + if (arg.hasTag(JCTree.Tag.LAMBDA)) { + final JCTree.JCLambda lambda = (JCLambda) arg; + if (lambda.paramKind == JCLambda.ParameterKind.IMPLICIT) { + for (JCVariableDecl var : lambda.params) { + var.vartype = null; //reset type + } + } + if (types.isFunctionalInterface(formal)) { + Type functionalType = types.findDescriptorType(formal); + boolean voidCompatible = functionalType.getReturnType().hasTag(TypeTag.VOID); + lambda.body = new TreeTranslator() { + @Override + public void visitReturn(JCReturn tree) { + result = tree; + if (voidCompatible) { + if (tree.expr != null) { + JCErroneous err = make.Erroneous(List.of(tree)); + result = err; + rollback.append(() -> { + lambda.body = new TreeTranslator() { + @SuppressWarnings("unchecked") + public <T extends JCTree> T translate(T t) { + if (t == err) return (T) tree; + else return super.translate(t); + } + }.translate(lambda.body); + }); + } + } else { + if (tree.expr == null) { + tree.expr = make.Erroneous().setType(syms.errType); + rollback.append(() -> { + tree.expr = null; + }); + } + } + } + @Override + public void visitLambda(JCLambda tree) { + //do not touch nested lambdas + } + @Override + public void visitClassDef(JCClassDecl tree) { + //do not touch nested classes + } + }.translate(lambda.body); + if (!voidCompatible) { + JCReturn ret = make.Return(make.Erroneous().setType(syms.errType)); + ((JCBlock) lambda.body).stats = ((JCBlock) lambda.body).stats.append(ret); + rollback.append(() -> { + ((JCBlock) lambda.body).stats = List.filter(((JCBlock) lambda.body).stats, ret); + }); + } + } + repaired = true; + } + args = args.tail; + if (formals.tail.nonEmpty() || !vararg) { + formals = formals.tail; + } + } + List<JCExpression> prevArgs = mit.args; + while (formals.nonEmpty()) { + mit.args = mit.args.append(make.Erroneous().setType(syms.errType)); + formals = formals.tail; + repaired = true; + } + rollback.append(() -> { + mit.args = prevArgs; + }); + } + + Type owntype; + if (repaired) { + List<JCExpression> args = TreeInfo.args(todo.env.tree); + List<Type> pats = todo.resultInfo.pt.getParameterTypes(); + while (pats.length() < args.length()) { + pats = pats.append(syms.errType); + } + owntype = attr.checkMethod(todo.site, todo.candSym, + attr.new ResultInfo(todo.resultInfo.pkind, todo.resultInfo.pt.getReturnType(), todo.resultInfo.checkContext, todo.resultInfo.checkMode), + todo.env, args, pats, + todo.resultInfo.pt.getTypeArguments()); + rollback.stream().forEach(Runnable::run); + } else { + owntype = basicMethodInvocationRecovery(todo.tree, todo.site, todo.errSym, todo.env, todo.resultInfo); + } + todo.tree.type = owntype; + } + } + + Type recoverMethodInvocation(JCTree tree, + Type site, + Symbol sym, + Env<AttrContext> env, + ResultInfo resultInfo) { + if ((sym.flags_field & Flags.RECOVERABLE) != 0 && env.info.attributionMode.recover()) { + recoveryTodo.append(new RecoverTodo(tree, site, sym, ((RecoveryErrorType) sym.type).candidateSymbol, attr.copyEnv(env), resultInfo)); + return syms.errType; + } else { + return basicMethodInvocationRecovery(tree, site, sym, env, resultInfo); + } + } + + private Type basicMethodInvocationRecovery(JCTree tree, + Type site, + Symbol sym, + Env<AttrContext> env, + ResultInfo resultInfo) { + Type pt = resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase)); + Type owntype = attr.checkIdInternal(tree, site, sym, pt, env, resultInfo); + resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); + return owntype; + } + + void wrongMethodSymbolCandidate(TypeSymbol errSymbol, Symbol candSym, JCDiagnostic diag) { + List<JCDiagnostic> diags = List.of(diag); + boolean recoverable = false; + while (!recoverable && diags.nonEmpty()) { + JCDiagnostic d = diags.head; + diags = diags.tail; + switch (d.getCode()) { + case "compiler.misc.missing.ret.val": + case "compiler.misc.unexpected.ret.val": + case "compiler.misc.infer.arg.length.mismatch": + case "compiler.misc.arg.length.mismatch": + errSymbol.type = new RecoveryErrorType((Type.ErrorType) errSymbol.type, candSym); + errSymbol.flags_field |= Flags.RECOVERABLE; + return ; + default: + break; + } + for (Object a : d.getArgs()) { + if (a instanceof JCDiagnostic) { + diags = diags.prepend((JCDiagnostic) a); + } + } + } + } + + private static class RecoveryErrorType extends ErrorType { + public final Symbol candidateSymbol; + + public RecoveryErrorType(ErrorType original, Symbol candidateSymbol) { + super(original.getOriginalType(), original.tsym); + this.candidateSymbol = candidateSymbol; + } + + } + + private static class RecoverTodo { + public final JCTree tree; + public final Type site; + public final Symbol errSym; + public final Symbol candSym; + public final Env<AttrContext> env; + public final ResultInfo resultInfo; + + public RecoverTodo(JCTree tree, Type site, Symbol errSym, Symbol candSym, + Env<AttrContext> env, Attr.ResultInfo resultInfo) { + this.tree = tree; + this.site = site; + this.errSym = errSym; + this.candSym = candSym; + this.env = env; + this.resultInfo = resultInfo; + } + + } +} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index f1725857891..b59065c5511 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -630,14 +630,23 @@ Type checkCastable(DiagnosticPosition pos, Type found, Type req) { return checkCastable(pos, found, req, basicHandler); } Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { - if (types.isCastable(found, req, castWarner(pos, found, req))) { + if (checkCastable(pos, found, req, checkContext, castWarner(pos, found, req))) { return req; } else { - checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req))); return types.createErrorType(found); } } + boolean checkCastable(DiagnosticPosition pos, Type found, Type req, + CheckContext checkContext, Warner warner) { + if (types.isCastable(found, req, warner)) { + return true; + } else { + checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req))); + return false; + } + } + /** Check for redundant casts (i.e. where source type is a subtype of target type) * The problem should only be reported for non-292 cast */ @@ -1307,7 +1316,10 @@ && checkDisjoint(pos, flags, SEALED | NON_SEALED) && checkDisjoint(pos, flags, SEALED, - FINAL | NON_SEALED)) { + FINAL | NON_SEALED) + && checkDisjoint(pos, flags, + SEALED, + ANNOTATION)) { // skip } return flags & (mask | ~ExtendedStandardFlags) | implicit; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java index 66ed1834179..f64274ca4de 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java @@ -1329,20 +1329,28 @@ public void visitReference(JCMemberReference tree) { */ enum AttributionMode { /**Normal, non-speculative, attribution.*/ - FULL(false), + FULL(false, true), /**Speculative attribution on behalf of an Analyzer.*/ - ANALYZER(true), + ATTRIB_TO_TREE(true, true), + /**Speculative attribution on behalf of an Analyzer.*/ + ANALYZER(true, false), /**Speculative attribution.*/ - SPECULATIVE(true); + SPECULATIVE(true, false); - AttributionMode(boolean isSpeculative) { + AttributionMode(boolean isSpeculative, boolean recover) { this.isSpeculative = isSpeculative; + this.recover = recover; } boolean isSpeculative() { return isSpeculative; } + boolean recover() { + return recover; + } + final boolean isSpeculative; + final boolean recover; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java index b4dd7d84cc4..f70d1d72c4b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java @@ -480,9 +480,11 @@ public void visitClassDef(JCClassDecl tree) { // which contains this class in a non-static context // (its "enclosing instance class"), provided such a class exists. Symbol owner1 = owner; + owner1 = skipLambdaOwner(owner1); while (owner1.kind.matches(KindSelector.VAL_MTH) && (owner1.flags_field & STATIC) == 0) { owner1 = owner1.owner; + owner1 = skipLambdaOwner(owner1); } if (owner1.kind == TYP) { ct.setEnclosingType(owner1.type); @@ -517,6 +519,13 @@ private static boolean classNameMatchesFileName(ClassSymbol c, JavaFileObject.Kind.SOURCE); } + private Symbol skipLambdaOwner(Symbol currentOwner) { + while (currentOwner.type == syms.lambdaScopeMethodType) { + currentOwner = currentOwner.owner; + } + return currentOwner; + } + /** Complain about a duplicate class. */ protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) { log.error(pos, Errors.DuplicateClass(c.fullname)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index 095e5f68d28..1d67ec9bdc0 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2527,47 +2527,6 @@ JCTree generateRecordMethod(JCClassDecl tree, Name name, List<VarSymbol> vars, M } } - private String argsTypeSig(List<Type> typeList) { - LowerSignatureGenerator sg = new LowerSignatureGenerator(); - sg.assembleSig(typeList); - return sg.toString(); - } - - /** - * Signature Generation - */ - private class LowerSignatureGenerator extends Types.SignatureGenerator { - - /** - * An output buffer for type signatures. - */ - StringBuilder sb = new StringBuilder(); - - LowerSignatureGenerator() { - super(types); - } - - @Override - protected void append(char ch) { - sb.append(ch); - } - - @Override - protected void append(byte[] ba) { - sb.append(new String(ba)); - } - - @Override - protected void append(Name name) { - sb.append(name.toString()); - } - - @Override - public String toString() { - return sb.toString(); - } - } - /** * Creates an indy qualifier, helpful to be part of an indy invocation * @param site the site diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MatchBindingsComputer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MatchBindingsComputer.java index 07e48ff1838..7e44d52936e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MatchBindingsComputer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MatchBindingsComputer.java @@ -120,7 +120,7 @@ public MatchBindings binary(JCTree tree, MatchBindings lhsBindings, MatchBinding public MatchBindings finishBindings(JCTree tree, MatchBindings matchBindings) { switch (tree.getTag()) { case NOT: case AND: case OR: case BINDINGPATTERN: - case PARENS: case TYPETEST: + case PARENS: case TYPETEST: case DECONSTRUCTIONPATTERN: case CONDEXPR: //error recovery: return matchBindings; default: diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index e855c240360..6fd598340b7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -96,6 +96,7 @@ public class Resolve { Log log; Symtab syms; Attr attr; + AttrRecover attrRecover; DeferredAttr deferredAttr; Check chk; Infer infer; @@ -126,6 +127,7 @@ protected Resolve(Context context) { names = Names.instance(context); log = Log.instance(context); attr = Attr.instance(context); + attrRecover = AttrRecover.instance(context); deferredAttr = DeferredAttr.instance(context); chk = Check.instance(context); infer = Infer.instance(context); @@ -4043,12 +4045,12 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, @Override public Symbol access(Name name, TypeSymbol location) { - Symbol sym = bestCandidate(); - return types.createErrorType(name, location, sym != null ? sym.type : syms.errSymbol.type).tsym; - } - - protected Symbol bestCandidate() { - return errCandidate().fst; + Pair<Symbol, JCDiagnostic> cand = errCandidate(); + TypeSymbol errSymbol = types.createErrorType(name, location, cand != null ? cand.fst.type : syms.errSymbol.type).tsym; + if (cand != null) { + attrRecover.wrongMethodSymbolCandidate(errSymbol, cand.fst, cand.snd); + } + return errSymbol; } protected Pair<Symbol, JCDiagnostic> errCandidate() { @@ -4181,11 +4183,12 @@ private List<JCDiagnostic> candidateDetails(Map<Symbol, JCDiagnostic> candidates } @Override - protected Symbol bestCandidate() { + protected Pair<Symbol, JCDiagnostic> errCandidate() { Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates(); Map<Symbol, JCDiagnostic> filteredCandidates = filterCandidates(candidatesMap); if (filteredCandidates.size() == 1) { - return filteredCandidates.keySet().iterator().next(); + return Pair.of(filteredCandidates.keySet().iterator().next(), + filteredCandidates.values().iterator().next()); } return null; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java index 4a97cf4c1c1..ee572e4d95f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java @@ -26,13 +26,13 @@ package com.sun.tools.javac.comp; import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Kinds.Kind; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.BindingSymbol; +import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symtab; -import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Types; -import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCBinary; import com.sun.tools.javac.tree.JCTree.JCConditional; @@ -58,18 +58,23 @@ import java.util.Map; import java.util.Map.Entry; +import java.util.LinkedHashMap; import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symbol.RecordComponent; +import com.sun.tools.javac.code.Type; import static com.sun.tools.javac.code.TypeTag.BOT; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCDeconstructionPattern; import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop; +import com.sun.tools.javac.tree.JCTree.JCPattern; import com.sun.tools.javac.tree.JCTree.JCLambda; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.LetExpr; import com.sun.tools.javac.util.List; -import java.util.HashMap; /** * This pass translates pattern-matching constructs, such as instanceof <pattern>. @@ -131,7 +136,8 @@ boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { boolean debugTransPatterns; - private MethodSymbol currentMethodSym = null; + private ClassSymbol currentClass; + private Symbol currentOwnerSym = null; protected TransPatterns(Context context) { context.put(transPatternsKey, this); @@ -148,38 +154,122 @@ protected TransPatterns(Context context) { @Override public void visitTypeTest(JCInstanceOf tree) { - if (tree.pattern.hasTag(Tag.BINDINGPATTERN)) { + if (tree.pattern.hasTag(Tag.BINDINGPATTERN) || tree.pattern.hasTag(Tag.DECONSTRUCTIONPATTERN)) { //E instanceof T N + //E instanceof T(PATT1, PATT2, ...) //=> - //(let T' N$temp = E; N$temp instanceof T && (N = (T) N$temp == (T) N$temp)) - JCBindingPattern patt = (JCBindingPattern)tree.pattern; - VarSymbol pattSym = patt.symbol; + //(let T' N$temp = E; N$temp instanceof T && <pattern extractor>) Type tempType = tree.expr.type.hasTag(BOT) ? syms.objectType : tree.expr.type; - VarSymbol temp = new VarSymbol(pattSym.flags() | Flags.SYNTHETIC, - names.fromString(pattSym.name.toString() + target.syntheticNameChar() + "temp"), + VarSymbol temp = new VarSymbol(Flags.SYNTHETIC, + names.fromString(target.syntheticNameChar() + "e" + target.syntheticNameChar()), tempType, - patt.symbol.owner); + currentOwnerSym); JCExpression translatedExpr = translate(tree.expr); - Type castTargetType = types.boxedTypeOrType(pattSym.erasure(types)); + Type castTargetType; + //TODO: use rule switch (when boot JDK is 14): + switch (tree.pattern.getTag()) { + case BINDINGPATTERN: + castTargetType = ((JCBindingPattern)tree.pattern).symbol.type; + break; + case DECONSTRUCTIONPATTERN: + castTargetType = ((JCDeconstructionPattern)tree.pattern).type; + break; + default: + throw new AssertionError("Unexpected pattern type: " + tree.pattern.getTag()); + } + + castTargetType = types.boxedTypeOrType(types.erasure(castTargetType)); - result = makeTypeTest(make.Ident(temp), make.Type(castTargetType)); + result = makeTypeTest(make.at(tree.pos).Ident(temp), make.Type(castTargetType)); + result = makeBinary(Tag.AND, (JCExpression)result, + preparePatternExtractor(tree, tree.getPattern(), temp, castTargetType)); + result = make.at(tree.pos).LetExpr(make.VarDef(temp, translatedExpr), + (JCExpression)result).setType(syms.booleanType); + ((LetExpr) result).needsCond = true; + } else { + super.visitTypeTest(tree); + } + } - VarSymbol bindingVar = bindingContext.bindingDeclared(patt.symbol); + private JCExpression preparePatternExtractor(JCInstanceOf tree, JCPattern patt, VarSymbol temp, Type targetType) { + if (targetType == syms.botType) { + targetType = syms.objectType; + } + if (patt.hasTag(Tag.BINDINGPATTERN)) { + //type test already done, finish handling of type test patterns ("T N") + //=> + //(let N = (T) N$temp; true) + VarSymbol bindingVar = bindingContext.bindingDeclared(((JCBindingPattern) patt).symbol); if (bindingVar != null) { //TODO: cannot be null here? JCAssign fakeInit = (JCAssign)make.at(tree.pos).Assign( - make.Ident(bindingVar), convert(make.Ident(temp), castTargetType)).setType(bindingVar.erasure(types)); + make.Ident(bindingVar), convert(make.Ident(temp), targetType)).setType(bindingVar.erasure(types)); LetExpr nestedLE = make.LetExpr(List.of(make.Exec(fakeInit)), make.Literal(true)); nestedLE.needsCond = true; nestedLE.setType(syms.booleanType); - result = makeBinary(Tag.AND, (JCExpression)result, nestedLE); + return nestedLE; } - result = make.at(tree.pos).LetExpr(make.VarDef(temp, translatedExpr), (JCExpression)result).setType(syms.booleanType); - ((LetExpr) result).needsCond = true; + return make.Literal(true); + } else if (patt.hasTag(Tag.DECONSTRUCTIONPATTERN)) { + //type test already done, finish handling of deconstruction patterns ("T(PATT1, PATT2, ...)") + //=> + //<PATT1-handling> && <PATT2-handling> && ... + JCDeconstructionPattern dpatt = (JCDeconstructionPattern) patt; + List<? extends RecordComponent> components = dpatt.record.getRecordComponents(); + List<? extends JCPattern> nestedPatterns = dpatt.nested; + JCExpression test = null; + while (components.nonEmpty() && nestedPatterns.nonEmpty()) { + //PATTn for record component COMPn of type Tn; + //PATTn is a type test pattern or a deconstruction pattern: + //=> + //(let Tn $c$COMPn = ((T) N$temp).COMPn(); <PATTn extractor>) + //or + //(let Tn $c$COMPn = ((T) N$temp).COMPn(); $c$COMPn != null && <PATTn extractor>) + //or + //(let Tn $c$COMPn = ((T) N$temp).COMPn(); $c$COMPn instanceof T' && <PATTn extractor>) + RecordComponent component = components.head; + JCPattern nested = nestedPatterns.head; + VarSymbol nestedTemp = new VarSymbol(Flags.SYNTHETIC, + names.fromString(target.syntheticNameChar() + "c" + target.syntheticNameChar() + component.name), + component.erasure(types), + currentOwnerSym); + Symbol accessor = dpatt.record + .members() + .findFirst(component.name, s -> s.kind == Kind.MTH && + ((MethodSymbol) s).params.isEmpty()); + JCVariableDecl nestedTempVar = + make.VarDef(nestedTemp, + make.App(make.Select(convert(make.Ident(temp), dpatt.type), + accessor))); + JCExpression extracted = + preparePatternExtractor(tree, nested, nestedTemp, nested.type); + JCExpression extraTest = null; + if (!types.isAssignable(nestedTemp.type, nested.type)) { + extraTest = makeTypeTest(make.Ident(nestedTemp), + make.Type(nested.type)); + } else if (nested.type.isReference()) { + extraTest = makeBinary(Tag.NE, make.Ident(nestedTemp), makeNull()); + } + if (extraTest != null) { + extracted = makeBinary(Tag.AND, extraTest, extracted); + } + LetExpr getAndRun = make.LetExpr(nestedTempVar, extracted); + getAndRun.needsCond = true; + getAndRun.setType(syms.booleanType); + if (test == null) { + test = getAndRun; + } else { + test = makeBinary(Tag.AND, test, getAndRun); + } + components = components.tail; + nestedPatterns = nestedPatterns.tail; + } + Assert.check(components.isEmpty() == nestedPatterns.isEmpty()); + return test != null ? test : make.Literal(true); } else { - super.visitTypeTest(tree); + throw new IllegalStateException(); } } @@ -251,12 +341,36 @@ public void visitDoLoop(JCDoWhileLoop tree) { @Override public void visitMethodDef(JCMethodDecl tree) { - MethodSymbol prevMethodSym = currentMethodSym; + Symbol prevOwnerSym = currentOwnerSym; try { - currentMethodSym = tree.sym; + currentOwnerSym = tree.sym; super.visitMethodDef(tree); } finally { - currentMethodSym = prevMethodSym; + currentOwnerSym = prevOwnerSym; + } + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + Symbol prevOwnerSym = currentOwnerSym; + try { + if (tree.sym.owner.kind == Kind.TYP) { + currentOwnerSym = tree.sym; + } + super.visitVarDef(tree); + } finally { + currentOwnerSym = prevOwnerSym; + } + } + + @Override + public void visitClassDef(JCClassDecl tree) { + ClassSymbol prevCurrentClass = currentClass; + try { + currentClass = tree.sym; + super.visitClassDef(tree); + } finally { + currentClass = prevCurrentClass; } } @@ -297,7 +411,13 @@ boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { return true; } }; + Symbol prevOwnerSym = currentOwnerSym; try { + if (currentOwnerSym == null) { + currentOwnerSym = new MethodSymbol(tree.flags | Flags.BLOCK, + names.empty, null, + currentClass); + } for (List<JCStatement> l = tree.stats; l.nonEmpty(); l = l.tail) { statements.append(translate(l.head)); } @@ -306,6 +426,7 @@ boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { result = tree; } finally { bindingContext.pop(); + currentOwnerSym = prevOwnerSym; } } @@ -355,6 +476,22 @@ JCBinary makeBinary(JCTree.Tag optag, JCExpression lhs, JCExpression rhs) { return tree; } + /** Make an attributed tree representing a literal. This will be an + * Ident node in the case of boolean literals, a Literal node in all + * other cases. + * @param type The literal's type. + * @param value The literal's value. + */ + JCExpression makeLit(Type type, Object value) { + return make.Literal(type.getTag(), value).setType(type.constType(value)); + } + + /** Make an attributed tree representing null. + */ + JCExpression makeNull() { + return makeLit(syms.botType, null); + } + JCExpression convert(JCExpression expr, Type target) { JCExpression result = make.at(expr.pos()).TypeCast(make.Type(target), expr); result.type = target; @@ -376,7 +513,7 @@ class BasicBindingContext extends BindingContext { public BasicBindingContext() { this.parent = bindingContext; - this.hoistedVarMap = new HashMap<>(); + this.hoistedVarMap = new LinkedHashMap<>(); } @Override diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java index fb33a7b0d7f..e737230a3ae 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -585,6 +585,13 @@ public void visitSwitchExpression(JCSwitchExpression tree) { result = retype(tree, tree.type, pt); } + @Override + public void visitDeconstructionPattern(JCDeconstructionPattern tree) { + tree.deconstructor = translate(tree.deconstructor, null); + tree.nested = translate(tree.nested, null); + result = tree; + } + public void visitSynchronized(JCSynchronized tree) { tree.lock = translate(tree.lock, erasure(tree.lock.type)); tree.body = translate(tree.body); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java index 124fa61f4e8..55a934fd3fb 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java @@ -45,6 +45,7 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCConditional; import com.sun.tools.javac.tree.JCTree.JCContinue; +import com.sun.tools.javac.tree.JCTree.JCDeconstructionPattern; import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop; import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCErroneous; @@ -266,6 +267,14 @@ public void visitBindingPattern(JCBindingPattern tree) { equiv.put(tree.symbol, that.symbol); } + @Override + public void visitDeconstructionPattern(JCTree.JCDeconstructionPattern tree) { + JCDeconstructionPattern that = (JCDeconstructionPattern) parameter; + result = + scan(tree.deconstructor, that.deconstructor) + && scan(tree.nested, that.nested); + } + @Override public void visitBlock(JCBlock tree) { JCBlock that = (JCBlock) parameter; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index c4dd360812d..c4098479b59 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -144,6 +144,9 @@ public class ClassWriter extends ClassFile { /** Access to files. */ private final JavaFileManager fileManager; + /** The symbol table. */ + private final Symtab syms; + /** The tags and constants used in compressed stackmap. */ static final int SAME_FRAME_SIZE = 64; static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247; @@ -182,6 +185,8 @@ protected ClassWriter(Context context) { emitSourceFile = options.isUnset(G_CUSTOM) || options.isSet(G_CUSTOM, "source"); + syms = Symtab.instance(context); + String modifierFlags = options.get("debug.dumpmodifiers"); if (modifierFlags != null) { dumpClassModifiers = modifierFlags.indexOf('c') != -1; @@ -328,7 +333,7 @@ protected int writeEnclosingMethodAttribute(Name attributeName, ClassSymbol c) { int alenIdx = writeAttr(attributeName); ClassSymbol enclClass = c.owner.enclClass(); MethodSymbol enclMethod = - (c.owner.type == null // local to init block + (c.owner.type == syms.blockScopeMethodType // local to init block || c.owner.kind != MTH) // or member init ? null : ((MethodSymbol)c.owner).originalEnclosingMethod(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java index 94809475200..440df2a35fa 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java @@ -248,7 +248,7 @@ protected List<DCTree> blockContent(Phase phase) { */ protected List<DCTree> blockTags() { ListBuffer<DCTree> tags = new ListBuffer<>(); - while (ch == '@') + while (bp < buflen && ch == '@') tags.add(blockTag()); return tags.toList(); } @@ -354,7 +354,7 @@ private enum WhitespaceRetentionPolicy { * Matching pairs of { } are skipped; the text is terminated by the first * unmatched }. It is an error if the beginning of the next tag is detected. */ - private DCTree inlineText(WhitespaceRetentionPolicy whitespacePolicy) throws ParseException { + private DCText inlineText(WhitespaceRetentionPolicy whitespacePolicy) throws ParseException { switch (whitespacePolicy) { case REMOVE_ALL: skipWhitespace(); @@ -663,14 +663,14 @@ protected DCTree entity() { nextChar(); if (isDecimalDigit(ch)) { nextChar(); - while (isDecimalDigit(ch)) + while (bp < buflen && isDecimalDigit(ch)) nextChar(); name = names.fromChars(buf, namep, bp - namep); } else if (ch == 'x' || ch == 'X') { nextChar(); if (isHexDigit(ch)) { nextChar(); - while (isHexDigit(ch)) + while (bp < buflen && isHexDigit(ch)) nextChar(); name = names.fromChars(buf, namep, bp - namep); } @@ -843,7 +843,7 @@ private DCTree html() { nextChar(); while (bp < buflen) { int dash = 0; - while (ch == '-') { + while (bp < buflen && ch == '-') { dash++; nextChar(); } @@ -890,7 +890,7 @@ protected List<DCTree> htmlAttrs() { skipWhitespace(); loop: - while (isIdentifierStart(ch)) { + while (bp < buflen && isIdentifierStart(ch)) { int namePos = bp; Name name = readAttributeName(); skipWhitespace(); @@ -1057,7 +1057,7 @@ protected boolean isWhitespace(char ch) { } protected void skipWhitespace() { - while (isWhitespace(ch)) { + while (bp < buflen && isWhitespace(ch)) { nextChar(); } } @@ -1118,9 +1118,9 @@ public DCTree parse(int pos) { new TagParser(TagParser.Kind.INLINE, DCTree.Kind.CODE, true) { @Override public DCTree parse(int pos) throws ParseException { - DCTree text = inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE); + DCText text = inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE); nextChar(); - return m.at(pos).newCodeTree((DCText) text); + return m.at(pos).newCodeTree(text); } }, @@ -1228,9 +1228,9 @@ public DCTree parse(int pos) throws ParseException { new TagParser(TagParser.Kind.INLINE, DCTree.Kind.LITERAL, true) { @Override public DCTree parse(int pos) throws ParseException { - DCTree text = inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE); + DCText text = inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE); nextChar(); - return m.at(pos).newLiteralTree((DCText) text); + return m.at(pos).newLiteralTree(text); } }, diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 4ffef19e081..49896495506 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -239,6 +239,7 @@ protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFact * mode = NOPARAMS : no parameters allowed for type * mode = TYPEARG : type argument * mode |= NOLAMBDA : lambdas are not allowed + * mode |= NOINVOCATION : method invocations are not allowed */ protected static final int EXPR = 0x1; protected static final int TYPE = 0x2; @@ -246,13 +247,14 @@ protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFact protected static final int TYPEARG = 0x8; protected static final int DIAMOND = 0x10; protected static final int NOLAMBDA = 0x20; + protected static final int NOINVOCATION = 0x40; protected void selectExprMode() { - mode = (mode & NOLAMBDA) | EXPR; + mode = (mode & (NOLAMBDA | NOINVOCATION)) | EXPR; } protected void selectTypeMode() { - mode = (mode & NOLAMBDA) | TYPE; + mode = (mode & (NOLAMBDA|NOINVOCATION)) | TYPE; } /** The current mode. @@ -564,10 +566,14 @@ public int getEndPos(JCTree tree) { * Ident = IDENTIFIER */ public Name ident() { - return ident(false); + return ident(false, false); } protected Name ident(boolean advanceOnErrors) { + return ident(advanceOnErrors, false); + } + + protected Name ident(boolean advanceOnErrors, boolean underscoreAllowed) { if (token.kind == IDENTIFIER) { Name name = token.name(); nextToken(); @@ -593,10 +599,16 @@ protected Name ident(boolean advanceOnErrors) { return names.error; } } else if (token.kind == UNDERSCORE) { - if (Feature.UNDERSCORE_IDENTIFIER.allowedInSource(source)) { - log.warning(token.pos, Warnings.UnderscoreAsIdentifier); - } else { - log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UnderscoreAsIdentifier); + if (!underscoreAllowed) { + if (Feature.UNDERSCORE_AS_PARAM_NAME.allowedInSource(source)) { + log.error(token.pos, Errors.UnderscoreNotAllowed); + } else { + if (Feature.UNDERSCORE_IDENTIFIER.allowedInSource(source)) { + log.warning(token.pos, Warnings.UnderscoreAsIdentifier); + } else { + log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UnderscoreAsIdentifier); + } + } } Name name = token.name(); nextToken(); @@ -614,7 +626,11 @@ protected Name ident(boolean advanceOnErrors) { * Qualident = Ident { DOT [Annotations] Ident } */ public JCExpression qualident(boolean allowAnnos) { - JCExpression t = toP(F.at(token.pos).Ident(ident())); + return qualident(allowAnnos, false); + } + + public JCExpression qualident(boolean allowAnnos, boolean underscoreAllowed) { + JCExpression t = toP(F.at(token.pos).Ident(ident(false, underscoreAllowed))); while (token.kind == DOT) { int pos = token.pos; nextToken(); @@ -754,6 +770,31 @@ public JCExpression parseExpression() { return term(EXPR); } + /** parses patterns. + */ + + public JCPattern parsePattern() { + int pos = token.pos; + if (token.kind == IDENTIFIER && token.name() == names.var) { + nextToken(); + return toP(F.at(pos).BindingPattern(ident(), null)); + } else { + JCExpression e = term(EXPR | TYPE | NOLAMBDA | NOINVOCATION); + if (token.kind == LPAREN) { + ListBuffer<JCPattern> nested = new ListBuffer<>(); + do { + nextToken(); + JCPattern nestedPattern = parsePattern(); + nested.append(nestedPattern); + } while (token.kind == COMMA); + accept(RPAREN); + return toP(F.at(pos).DeconstructionPattern(e, nested.toList())); + } else { + return toP(F.at(pos).BindingPattern(ident(), e)); + } + } + } + /** * parses (optional) type annotations followed by a type. If the * annotations are present before the type and are not consumed during array @@ -936,6 +977,16 @@ JCExpression term2Rest(JCExpression t, int minprec) { if (token.kind == IDENTIFIER) { checkSourceLevel(token.pos, Feature.PATTERN_MATCHING_IN_INSTANCEOF); pattern = toP(F.at(token.pos).BindingPattern(ident(), pattern)); + } else if (token.kind == LPAREN) { + checkSourceLevel(Feature.DECONSTRUCTION_PATTERNS); + ListBuffer<JCPattern> nested = new ListBuffer<>(); + do { + nextToken(); + JCPattern nestedPattern = parsePattern(); + nested.append(nestedPattern); + } while (token.kind == COMMA); + accept(RPAREN); + pattern = toP(F.at(pattern).DeconstructionPattern((JCExpression) pattern, nested.toList())); } odStack[top] = F.at(pos).TypeTest(odStack[top], pattern); } else { @@ -1265,7 +1316,7 @@ protected JCExpression term3() { } break loop; case LPAREN: - if ((mode & EXPR) != 0) { + if ((mode & EXPR) != 0 && (mode & NOINVOCATION) == 0) { selectExprMode(); t = arguments(typeArgs, t); if (!annos.isEmpty()) t = illegal(annos.head.pos); @@ -1795,7 +1846,7 @@ enum ParensResult { JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { List<JCVariableDecl> params = explicitParams ? - formalParameters(true, false) : + formalParameters(FormalParameterKind.LAMBDA) : implicitParameters(hasParens); if (explicitParams) { LambdaClassifier lambdaClassifier = new LambdaClassifier(); @@ -2873,7 +2924,7 @@ protected JCCatch catchClause() { JCExpression paramType = catchTypes.size() > 1 ? toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) : catchTypes.head; - JCVariableDecl formal = variableDeclaratorId(mods, paramType); + JCVariableDecl formal = variableDeclaratorId(mods, paramType, FormalParameterKind.CATCH); accept(RPAREN); JCBlock body = block(); return F.at(pos).Catch(formal, body); @@ -3370,26 +3421,61 @@ Source restrictedTypeNameStartingAtSource(Name name, int pos, boolean shouldWarn return null; } + /** The kind of a formal parameter + */ + enum FormalParameterKind { + /* a formal lambda parameter + */ + LAMBDA { + @Override + boolean isLambdaParameter() { + return true; + } + }, + /* a formal catch clause parameter + */ + CATCH, + /* a formal method parameter + */ + METHOD, + /* a formal record parameter + */ + RECORD; + + boolean isLambdaParameter() { + return false; + } + boolean isRecordParameter() { + return false; + } + } + /** VariableDeclaratorId = Ident BracketsOpt */ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { - return variableDeclaratorId(mods, type, false, false); + return variableDeclaratorId(mods, type, FormalParameterKind.METHOD); } - //where - JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter, boolean recordComponent) { + + JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, FormalParameterKind parameterKind) { int pos = token.pos; Name name; - if (lambdaParameter && token.kind == UNDERSCORE) { + boolean allowUnderscoreAsFormal = Feature.UNDERSCORE_AS_PARAM_NAME.allowedInSource(source); + boolean isUnderscore = token.kind == UNDERSCORE; + if (parameterKind.isLambdaParameter() && isUnderscore && !allowUnderscoreAsFormal) { log.error(pos, Errors.UnderscoreAsIdentifierInLambda); name = token.name(); nextToken(); + } else if (parameterKind == FormalParameterKind.METHOD && isUnderscore && allowUnderscoreAsFormal) { + log.error(pos, Errors.UnderscoreAsIdentifierInMethod); + name = token.name(); + nextToken(); } else { if (allowThisIdent || - !lambdaParameter || + parameterKind != FormalParameterKind.LAMBDA || LAX_IDENTIFIER.accepts(token.kind) || mods.flags != Flags.PARAMETER || mods.annotations.nonEmpty()) { - JCExpression pn = qualident(false); + JCExpression pn = qualident(false, allowUnderscoreAsFormal); if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) { name = ((JCIdent)pn).name; } else { @@ -3421,12 +3507,16 @@ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean token.kind == LBRACKET) { log.error(token.pos, Errors.VarargsAndOldArraySyntax); } - if (recordComponent && token.kind == LBRACKET) { + if (parameterKind == FormalParameterKind.RECORD && token.kind == LBRACKET) { log.error(token.pos, Errors.RecordComponentAndOldArraySyntax); } - type = bracketsOpt(type); - return toP(F.at(pos).VarDef(mods, name, type, null)); + int dimensionsPos = token.pos; + JCExpression typeWithDimensions = bracketsOpt(type); + if (allowUnderscoreAsFormal && isUnderscore && typeWithDimensions != type) { + log.error(dimensionsPos, Errors.UnderscoreCantBeFollowedByDimensions); + } + return toP(F.at(pos).VarDef(mods, name, typeWithDimensions, null)); } /** Resources = Resource { ";" Resources } @@ -3780,7 +3870,7 @@ protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) { List<JCTypeParameter> typarams = typeParametersOpt(); - List<JCVariableDecl> headerFields = formalParameters(false, true); + List<JCVariableDecl> headerFields = formalParameters(FormalParameterKind.RECORD); List<JCExpression> implementing = List.nil(); if (token.kind == IMPLEMENTS) { @@ -4256,11 +4346,19 @@ protected boolean isSealedClassStart(boolean local) { private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) { return local ? switch (next.kind) { - case MONKEYS_AT, ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true; + case MONKEYS_AT -> { + Token afterNext = S.token(2); + yield afterNext.kind != INTERFACE || currentIsNonSealed; + } + case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true; default -> false; } : switch (next.kind) { - case MONKEYS_AT, PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true; + case MONKEYS_AT -> { + Token afterNext = S.token(2); + yield afterNext.kind != INTERFACE || currentIsNonSealed; + } + case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true; case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed; default -> false; }; @@ -4296,7 +4394,7 @@ protected JCTree methodDeclaratorRest(int pos, List<JCVariableDecl> params = List.nil(); List<JCExpression> thrown = List.nil(); if (!isRecord || name != names.init || token.kind == LPAREN) { - params = formalParameters(); + params = formalParameters(FormalParameterKind.METHOD); if (!isVoid) type = bracketsOpt(type); if (token.kind == THROWS) { nextToken(); @@ -4412,16 +4510,13 @@ JCTypeParameter typeParameter() { * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter */ - List<JCVariableDecl> formalParameters() { - return formalParameters(false, false); - } - List<JCVariableDecl> formalParameters(boolean lambdaParameters, boolean recordComponents) { + List<JCVariableDecl> formalParameters(FormalParameterKind parameterKind) { ListBuffer<JCVariableDecl> params = new ListBuffer<>(); JCVariableDecl lastParam; accept(LPAREN); if (token.kind != RPAREN) { - this.allowThisIdent = !lambdaParameters && !recordComponents; - lastParam = formalParameter(lambdaParameters, recordComponents); + this.allowThisIdent = parameterKind != FormalParameterKind.LAMBDA && parameterKind != FormalParameterKind.RECORD; + lastParam = formalParameter(parameterKind); if (lastParam.nameexpr != null) { this.receiverParam = lastParam; } else { @@ -4433,7 +4528,7 @@ List<JCVariableDecl> formalParameters(boolean lambdaParameters, boolean recordCo log.error(DiagnosticFlag.SYNTAX, lastParam, Errors.VarargsMustBeLast); } nextToken(); - params.append(lastParam = formalParameter(lambdaParameters, recordComponents)); + params.append(lastParam = formalParameter(parameterKind)); } } if (token.kind == RPAREN) { @@ -4544,18 +4639,18 @@ private JCExpression insertAnnotationsToMostInner( /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter */ - protected JCVariableDecl formalParameter(boolean lambdaParameter, boolean recordComponent) { - JCModifiers mods = !recordComponent ? optFinal(Flags.PARAMETER) : modifiersOpt(); - if (recordComponent && mods.flags != 0) { + protected JCVariableDecl formalParameter(FormalParameterKind parameterKind) { + JCModifiers mods = parameterKind != FormalParameterKind.RECORD ? optFinal(Flags.PARAMETER) : modifiersOpt(); + if (parameterKind == FormalParameterKind.RECORD && mods.flags != 0) { log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers); } - if (recordComponent) { + if (parameterKind == FormalParameterKind.RECORD) { mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE | Flags.GENERATED_MEMBER; } // need to distinguish between vararg annos and array annos // look at typeAnnotationsPushedBack comment this.permitTypeAnnotationsPushBack = true; - JCExpression type = parseType(lambdaParameter); + JCExpression type = parseType(parameterKind == FormalParameterKind.LAMBDA); this.permitTypeAnnotationsPushBack = false; if (token.kind == ELLIPSIS) { @@ -4572,12 +4667,12 @@ protected JCVariableDecl formalParameter(boolean lambdaParameter, boolean record } typeAnnotationsPushedBack = List.nil(); } - return variableDeclaratorId(mods, type, lambdaParameter, recordComponent); + return variableDeclaratorId(mods, type, parameterKind); } protected JCVariableDecl implicitParameter() { JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); - return variableDeclaratorId(mods, null, true, false); + return variableDeclaratorId(mods, null, FormalParameterKind.LAMBDA); } /* ---------- auxiliary methods -------------- */ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 01edf5eb90a..3acebee5cdd 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2944,6 +2944,9 @@ compiler.misc.feature.pattern.matching.instanceof=\ compiler.misc.feature.reifiable.types.instanceof=\ reifiable types in instanceof +compiler.misc.feature.deconstruction.patterns=\ + deconstruction patterns + compiler.misc.feature.records=\ records @@ -2956,10 +2959,20 @@ compiler.warn.underscore.as.identifier=\ compiler.err.underscore.as.identifier=\ as of release 9, ''_'' is a keyword, and may not be used as an identifier +compiler.err.underscore.not.allowed=\ + as of release 10, '_' can only be used as an unused formal parameter. + +compiler.err.underscore.cant.be.followed.by.dimensions=\ + parameter name ''_'' cannot be followed by dimensions + compiler.err.underscore.as.identifier.in.lambda=\ ''_'' used as an identifier\n\ (use of ''_'' as an identifier is forbidden for lambda parameters) +compiler.err.underscore.as.identifier.in.method=\ + ''_'' used as an identifier\n\ + (use of ''_'' as an identifier is forbidden for method parameters) + compiler.err.enum.as.identifier=\ as of release 5, ''enum'' is a keyword, and may not be used as an identifier @@ -3742,3 +3755,13 @@ compiler.err.preview.not.latest=\ compiler.err.preview.without.source.or.release=\ --enable-preview must be used with either -source or --release + +# 0: symbol +compiler.err.deconstruction.pattern.only.records=\ + deconstruction patterns can only be applied to records, {0} is not a record + +# 0: list of type, 1: list of type +compiler.err.incorrect.number.of.nested.patterns=\ + incorrect number of nested patterns\n\ + required: {0}\n\ + found: {1} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java index 7a237840852..b786f4cfd51 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java @@ -161,14 +161,14 @@ public DocTreeMaker at(DiagnosticPosition pos) { } @Override @DefinedBy(Api.COMPILER_TREE) - public DCAttribute newAttributeTree(javax.lang.model.element.Name name, ValueKind vkind, java.util.List<? extends DocTree> value) { + public DCAttribute newAttributeTree(Name name, ValueKind vkind, List<? extends DocTree> value) { DCAttribute tree = new DCAttribute(name, vkind, cast(value)); tree.pos = pos; return tree; } @Override @DefinedBy(Api.COMPILER_TREE) - public DCAuthor newAuthorTree(java.util.List<? extends DocTree> name) { + public DCAuthor newAuthorTree(List<? extends DocTree> name) { DCAuthor tree = new DCAuthor(cast(name)); tree.pos = pos; return tree; @@ -197,11 +197,7 @@ public DCDeprecated newDeprecatedTree(List<? extends DocTree> text) { @Override @DefinedBy(Api.COMPILER_TREE) public DCDocComment newDocCommentTree(List<? extends DocTree> fullBody, List<? extends DocTree> tags) { - Pair<List<DCTree>, List<DCTree>> pair = splitBody(fullBody); - List<DCTree> preamble = Collections.emptyList(); - List<DCTree> postamble = Collections.emptyList(); - - return newDocCommentTree(fullBody, tags, preamble, postamble); + return newDocCommentTree(fullBody, tags, Collections.emptyList(), Collections.emptyList()); } public DCDocComment newDocCommentTree(Comment comment, @@ -503,7 +499,7 @@ public DCVersion newVersionTree(List<? extends DocTree> text) { } @Override @DefinedBy(Api.COMPILER_TREE) - public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) { + public List<DocTree> getFirstSentence(List<? extends DocTree> list) { Pair<List<DCTree>, List<DCTree>> pair = splitBody(list); return new ArrayList<>(pair.fst); } @@ -693,7 +689,7 @@ private int getSentenceBreak(String s, DocTree dt) { return -1; // indeterminate at this time } - private boolean isSentenceBreak(javax.lang.model.element.Name tagName) { + private boolean isSentenceBreak(Name tagName) { return sentenceBreakTags.contains(get(tagName)); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java index 743f46af459..019a94925bf 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -241,6 +241,8 @@ public enum Tag { */ BINDINGPATTERN, + DECONSTRUCTIONPATTERN, + /** Indexed array expressions, of type Indexed. */ INDEXED, @@ -2237,6 +2239,55 @@ public Tag getTag() { } } + public static class JCDeconstructionPattern extends JCPattern + implements DeconstructionPatternTree { + public JCExpression deconstructor; + public List<JCPattern> nested; + public ClassSymbol record; + public List<Type> innerTypes; + + protected JCDeconstructionPattern(JCExpression deconstructor, List<JCPattern> nested) { + this.deconstructor = deconstructor; + this.nested = nested; + } + + @DefinedBy(Api.COMPILER_TREE) + public Name getBinding() { + return null; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Tree getDeconstructor() { + return deconstructor; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public List<? extends JCPattern> getNestedPatterns() { + return nested; + } + + @Override + public void accept(Visitor v) { + v.visitDeconstructionPattern(this); + } + + @DefinedBy(Api.COMPILER_TREE) + public Kind getKind() { + return Kind.DECONSTRUCTION_PATTERN; + } + + @Override + @DefinedBy(Api.COMPILER_TREE) + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitDeconstructionPattern(this, d); + } + + @Override + public Tag getTag() { + return DECONSTRUCTIONPATTERN; + } + } + /** * An array selection */ @@ -3277,6 +3328,7 @@ public static abstract class Visitor { public void visitTypeCast(JCTypeCast that) { visitTree(that); } public void visitTypeTest(JCInstanceOf that) { visitTree(that); } public void visitBindingPattern(JCBindingPattern that) { visitTree(that); } + public void visitDeconstructionPattern(JCDeconstructionPattern that) { visitTree(that); } public void visitIndexed(JCArrayAccess that) { visitTree(that); } public void visitSelect(JCFieldAccess that) { visitTree(that); } public void visitReference(JCMemberReference that) { visitTree(that); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java index 48aa07d56e6..de7c1f6f663 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -903,6 +903,18 @@ public void visitBindingPattern(JCBindingPattern patt) { } } + @Override + public void visitDeconstructionPattern(JCDeconstructionPattern tree) { + try { + printExpr(tree.deconstructor); + print("("); + printExprs(tree.nested); + print(")"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitSynchronized(JCSynchronized tree) { try { print("synchronized "); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java index 5c1edf76096..717216d1691 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -497,6 +497,14 @@ public JCTree visitBindingPattern(BindingPatternTree node, P p) { return M.at(t.pos).BindingPattern(t.name, vartype); } + @DefinedBy(Api.COMPILER_TREE) + public JCTree visitDeconstructionPattern(DeconstructionPatternTree node, P p) { + JCDeconstructionPattern t = (JCDeconstructionPattern) node; + JCExpression deconstructor = copy(t.deconstructor, p); + List<JCPattern> nested = copy(t.nested, p); + return M.at(t.pos).DeconstructionPattern(deconstructor, nested); + } + @DefinedBy(Api.COMPILER_TREE) public JCTree visitUnary(UnaryTree node, P p) { JCUnary t = (JCUnary) node; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 8da7b73fbbc..13856ce7e20 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -482,6 +482,12 @@ public JCBindingPattern BindingPattern(Name name, JCTree vartype) { return tree; } + public JCDeconstructionPattern DeconstructionPattern(JCExpression deconstructor, List<JCPattern> nested) { + JCDeconstructionPattern tree = new JCDeconstructionPattern(deconstructor, nested); + tree.pos = pos; + return tree; + } + public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) { JCArrayAccess tree = new JCArrayAccess(indexed, index); tree.pos = pos; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java index e1c2d5595c1..92aac7fd7de 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -308,6 +308,12 @@ public void visitBindingPattern(JCBindingPattern tree) { scan(tree.vartype); } + @Override + public void visitDeconstructionPattern(JCDeconstructionPattern that) { + scan(that.deconstructor); + scan(that.nested); + } + public void visitIndexed(JCArrayAccess tree) { scan(tree.indexed); scan(tree.index); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java index 26fea8f0e47..19d6908e9a3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java @@ -457,6 +457,13 @@ public void visitAnnotatedType(JCAnnotatedType tree) { result = tree; } + @Override + public void visitDeconstructionPattern(JCDeconstructionPattern tree) { + tree.deconstructor = translate(tree.deconstructor); + tree.nested = translate(tree.nested); + result = tree; + } + public void visitTree(JCTree tree) { throw new AssertionError(tree); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java index 90e9c685ad7..42dd43a8158 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java @@ -186,6 +186,7 @@ public static Names instance(Context context) { public final Name module_info; public final Name package_info; public final Name requireNonNull; + public final Name underscore; // lambda-related public final Name lambda; @@ -360,6 +361,7 @@ public Names(Context context) { module_info = fromString("module-info"); package_info = fromString("package-info"); requireNonNull = fromString("requireNonNull"); + underscore = fromString("_"); //lambda-related lambda = fromString("lambda$"); diff --git a/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocFormatter.java b/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocFormatter.java index 9c9d36b507a..fb031ae3f77 100644 --- a/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocFormatter.java +++ b/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,6 @@ import com.sun.source.util.DocTreeScanner; import com.sun.source.util.DocTrees; import com.sun.source.util.JavacTask; -import com.sun.tools.doclint.Entity; import com.sun.tools.doclint.HtmlTag; import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; @@ -128,6 +127,7 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept private class FormatJavadocScanner extends DocTreeScanner<Object, Object> { private final StringBuilder result; private final JavacTask task; + private final DocTrees trees; private int reflownTo; private int indent; private int limit = Math.min(lineLimit, MAX_LINE_LENGTH); @@ -137,6 +137,7 @@ private class FormatJavadocScanner extends DocTreeScanner<Object, Object> { public FormatJavadocScanner(StringBuilder result, JavacTask task) { this.result = result; this.task = task; + this.trees = DocTrees.instance(task); } @Override @DefinedBy(Api.COMPILER_TREE) @@ -511,31 +512,10 @@ private void handleEndElement(Name name) { @Override @DefinedBy(Api.COMPILER_TREE) public Object visitEntity(EntityTree node, Object p) { - String name = node.getName().toString(); - int code = -1; - String value = null; - if (name.startsWith("#")) { - try { - int v = StringUtils.toLowerCase(name).startsWith("#x") - ? Integer.parseInt(name.substring(2), 16) - : Integer.parseInt(name.substring(1), 10); - if (Entity.isValid(v)) { - code = v; - } - } catch (NumberFormatException ex) { - //ignore - } - } else { - value = Entity.getValue(name); - } - if (code != (-1)) { - result.appendCodePoint(code); - } else if (value != null) { - result.append(value); - } else { - result.append(node.toString()); - } + String value = trees.getCharacters(node); + result.append(value == null ? node.toString() : value); return super.visitEntity(node, p); + } private DocTree lastNode; diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java index 5f34d123a4a..41c18e91f7b 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java @@ -46,12 +46,20 @@ * . "SHA256withECDSA" * . "SHA384withECDSA" * . "SHA512withECDSA" + * . "SHA3-224withECDSA" + * . "SHA3-256withECDSA" + * . "SHA3-384withECDSA" + * . "SHA3-512withECDSA" * . "NONEwithECDSAinP1363Format" * . "SHA1withECDSAinP1363Format" * . "SHA224withECDSAinP1363Format" * . "SHA256withECDSAinP1363Format" * . "SHA384withECDSAinP1363Format" * . "SHA512withECDSAinP1363Format" + * . "SHA3-224withECDSAinP1363Format" + * . "SHA3-256withECDSAinP1363Format" + * . "SHA3-384withECDSAinP1363Format" + * . "SHA3-512withECDSAinP1363Format" * * @since 1.7 */ @@ -278,6 +286,62 @@ public SHA512inP1363Format() { } } + // Nested class for SHA3_224withECDSA signatures + public static final class SHA3_224 extends ECDSASignature { + public SHA3_224() { + super("SHA3-224"); + } + } + + // Nested class for SHA3_224withECDSAinP1363Format signatures + public static final class SHA3_224inP1363Format extends ECDSASignature { + public SHA3_224inP1363Format() { + super("SHA3-224", true); + } + } + + // Nested class for SHA3_256withECDSA signatures + public static final class SHA3_256 extends ECDSASignature { + public SHA3_256() { + super("SHA3-256"); + } + } + + // Nested class for SHA3_256withECDSAinP1363Format signatures + public static final class SHA3_256inP1363Format extends ECDSASignature { + public SHA3_256inP1363Format() { + super("SHA3-256", true); + } + } + + // Nested class for SHA3_384withECDSA signatures + public static final class SHA3_384 extends ECDSASignature { + public SHA3_384() { + super("SHA3-384"); + } + } + + // Nested class for SHA3_384withECDSAinP1363Format signatures + public static final class SHA3_384inP1363Format extends ECDSASignature { + public SHA3_384inP1363Format() { + super("SHA3-384", true); + } + } + + // Nested class for SHA3_512withECDSA signatures + public static final class SHA3_512 extends ECDSASignature { + public SHA3_512() { + super("SHA3-512"); + } + } + + // Nested class for SHA3_512withECDSAinP1363Format signatures + public static final class SHA3_512inP1363Format extends ECDSASignature { + public SHA3_512inP1363Format() { + super("SHA3-512", true); + } + } + // initialize for verification. See JCA doc @Override protected void engineInitVerify(PublicKey publicKey) diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java index d84ffaa815c..e5c7d404c53 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java @@ -157,8 +157,20 @@ public Object newInstance(Object ctrParamObj) } else if (algo.equals("NONEwithECDSA")) { return (inP1363? new ECDSASignature.RawinP1363Format() : new ECDSASignature.Raw()); - } - } else if (type.equals("KeyFactory")) { + } else if (algo.equals("SHA3-224withECDSA")) { + return (inP1363? new ECDSASignature.SHA3_224inP1363Format() : + new ECDSASignature.SHA3_224()); + } else if (algo.equals("SHA3-256withECDSA")) { + return (inP1363? new ECDSASignature.SHA3_256inP1363Format() : + new ECDSASignature.SHA3_256()); + } else if (algo.equals("SHA3-384withECDSA")) { + return (inP1363? new ECDSASignature.SHA3_384inP1363Format() : + new ECDSASignature.SHA3_384()); + } else if (algo.equals("SHA3-512withECDSA")) { + return (inP1363? new ECDSASignature.SHA3_512inP1363Format() : + new ECDSASignature.SHA3_512()); + } + } else if (type.equals("KeyFactory")) { if (algo.equals("EC")) { return new ECKeyFactory(); } else if (algo.equals("XDH")) { @@ -304,6 +316,18 @@ void putEntries() { putService(new ProviderServiceA(this, "Signature", "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512", ATTRS)); + putService(new ProviderServiceA(this, "Signature", + "SHA3-224withECDSA", "sun.security.ec.ECDSASignature$SHA3_224", + ATTRS)); + putService(new ProviderServiceA(this, "Signature", + "SHA3-256withECDSA", "sun.security.ec.ECDSASignature$SHA3_256", + ATTRS)); + putService(new ProviderServiceA(this, "Signature", + "SHA3-384withECDSA", "sun.security.ec.ECDSASignature$SHA3_384", + ATTRS)); + putService(new ProviderServiceA(this, "Signature", + "SHA3-512withECDSA", "sun.security.ec.ECDSASignature$SHA3_512", + ATTRS)); putService(new ProviderService(this, "Signature", "NONEwithECDSAinP1363Format", @@ -324,6 +348,19 @@ void putEntries() { "SHA512withECDSAinP1363Format", "sun.security.ec.ECDSASignature$SHA512inP1363Format")); + putService(new ProviderService(this, "Signature", + "SHA3-224withECDSAinP1363Format", + "sun.security.ec.ECDSASignature$SHA3_224inP1363Format")); + putService(new ProviderService(this, "Signature", + "SHA3-256withECDSAinP1363Format", + "sun.security.ec.ECDSASignature$SHA3_256inP1363Format")); + putService(new ProviderService(this, "Signature", + "SHA3-384withECDSAinP1363Format", + "sun.security.ec.ECDSASignature$SHA3_384inP1363Format")); + putService(new ProviderService(this, "Signature", + "SHA3-512withECDSAinP1363Format", + "sun.security.ec.ECDSASignature$SHA3_512inP1363Format")); + /* * Key Pair Generator engine */ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java index 563827fe020..373db9a9868 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java @@ -100,8 +100,8 @@ public int contentions() { } // FIXME - // void* object_addr(); - // void set_object(void* obj); + // oop* object_addr(); + // void set_object(oop obj); // The following four either aren't expressed as typed fields in // vmStructs.cpp because they aren't strongly typed in the VM, or diff --git a/src/jdk.incubator.jpackage/linux/native/applauncher/LinuxLauncher.cpp b/src/jdk.incubator.jpackage/linux/native/applauncher/LinuxLauncher.cpp index 43d45eba025..69d3c30ae01 100644 --- a/src/jdk.incubator.jpackage/linux/native/applauncher/LinuxLauncher.cpp +++ b/src/jdk.incubator.jpackage/linux/native/applauncher/LinuxLauncher.cpp @@ -44,8 +44,6 @@ size_t hash(const std::string& str) { } void launchApp() { - setlocale(LC_ALL, "en_US.utf8"); - const tstring launcherPath = SysInfo::getProcessModulePath(); const Package ownerPackage = Package::findOwnerOfFile(launcherPath); diff --git a/src/jdk.incubator.jpackage/macosx/native/applauncher/MacLauncher.cpp b/src/jdk.incubator.jpackage/macosx/native/applauncher/MacLauncher.cpp index b9f8f17d5d8..3949716e514 100644 --- a/src/jdk.incubator.jpackage/macosx/native/applauncher/MacLauncher.cpp +++ b/src/jdk.incubator.jpackage/macosx/native/applauncher/MacLauncher.cpp @@ -67,7 +67,6 @@ void initJvmLauncher() { int main(int argc, char *argv[]) { - setlocale(LC_ALL, "en_US.utf8"); if (jvmLauncher) { // This is the call from the thread spawned by JVM. // Skip initialization phase as we have done this already in the first diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index 7a6d56e7f63..b323b69ea52 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -999,9 +999,9 @@ HotSpotResolvedObjectTypeImpl getResolvedJavaType(long displacement, boolean com /** * Adds phases in HotSpot JFR. * - * @see JFR.CompilerPhaseEvent#registerPhases and JFR.CompilerPhaseEvent#write + * @see JFR.CompilerPhaseEvent#write */ - native int registerCompilerPhases(String[] phases); + native int registerCompilerPhase(String phaseName); /** * @see JFR.CompilerPhaseEvent#write diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/JFR.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/JFR.java index 29fc59111df..7f6b99a2f43 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/JFR.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/JFR.java @@ -21,7 +21,6 @@ * questions. */ - package jdk.vm.ci.hotspot; import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; @@ -33,8 +32,9 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; /** - * Helper methods for interacting with the Java Flight Recorder (JFR) to register events and notify it when events occur. - * The JFR events are defined in {see @code src/share/jfr/metadata/metadata.xml}. + * Helper methods for interacting with the Java Flight Recorder (JFR) to register events and notify + * it when events occur. The JFR events are defined in {see @code + * src/share/jfr/metadata/metadata.xml}. */ public final class JFR { @@ -60,22 +60,7 @@ public static final class CompilerPhaseEvent { private static final ConcurrentHashMap<String, Integer> phaseToId = new ConcurrentHashMap<>(); private static int getPhaseToId(String phaseName) { - String[] phaseNames = { phaseName }; - return phaseToId.computeIfAbsent(phaseName, k -> compilerToVM().registerCompilerPhases(phaseNames)); - } - - /** - * Registers new compiler phases with JFR. This should be called during compiler initialization. - * - * @param phaseNames compiler phase names - */ - public static synchronized void registerPhases(String[] phaseNames) { - ArrayList<String> toProcess = new ArrayList<>(Arrays.asList(phaseNames)); - toProcess.removeAll(phaseToId.keySet()); - int pid = compilerToVM().registerCompilerPhases(toProcess.toArray(new String[toProcess.size()])); - for (String phase : toProcess) { - phaseToId.put(phase, pid++); - } + return phaseToId.computeIfAbsent(phaseName, k -> compilerToVM().registerCompilerPhase(phaseName)); } /** @@ -92,8 +77,8 @@ public static void write(long startTime, String phaseName, int compileId, int ph } /** - * Helper methods for managing JFR CompilerInlining events. - * The events are defined in {see @code src/share/jfr/metadata/metadata.xml}. + * Helper methods for managing JFR CompilerInlining events. The events are defined in {see @code + * src/share/jfr/metadata/metadata.xml}. */ public static final class CompilerInliningEvent { @@ -112,4 +97,3 @@ public static void write(int compileId, ResolvedJavaMethod caller, ResolvedJavaM } } } - diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java index f714e22a529..31ad7e48320 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java @@ -586,12 +586,14 @@ void validateAssignment(ValueContainer destination) */ JNITypeParser destSig = new JNITypeParser(destination.signature()); - JNITypeParser sourceSig = new JNITypeParser(type().signature()); if (destSig.isPrimitive()) { throw new InvalidTypeException("Can't assign object value to primitive"); } - if (destSig.isArray() && !sourceSig.isArray()) { - throw new InvalidTypeException("Can't assign non-array value to an array"); + if (destSig.isArray()) { + JNITypeParser sourceSig = new JNITypeParser(type().signature()); + if (!sourceSig.isArray()) { + throw new InvalidTypeException("Can't assign non-array value to an array"); + } } if (destSig.isVoid()) { throw new InvalidTypeException("Can't assign object value to a void"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java index f6fd0110592..aaa11b64c40 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java @@ -182,19 +182,13 @@ private List<Long> combineChunkSizes(List<Long> sizes, int maxChunks, long maxSi long fileSize = sizes.get(0); for (int i = 1; i < sizes.size(); i++) { long size = sizes.get(i); - if (fileSize + size > maxSize) { + if (fileSize + size > maxSize || chunks == maxChunks) { reduced.add(fileSize); chunks = 1; fileSize = size; continue; } fileSize += size; - if (chunks == maxChunks) { - reduced.add(fileSize); - fileSize = 0; - chunks = 1; - continue; - } chunks++; } if (fileSize != 0) { diff --git a/test/hotspot/gtest/metaprogramming/test_primitiveConversions.cpp b/test/hotspot/gtest/metaprogramming/test_primitiveConversions.cpp index 448295122bd..f143e28feee 100644 --- a/test/hotspot/gtest/metaprogramming/test_primitiveConversions.cpp +++ b/test/hotspot/gtest/metaprogramming/test_primitiveConversions.cpp @@ -95,6 +95,51 @@ TEST(PrimitiveConversionsTest, round_trip_int) { EXPECT_EQ(ufive, PrimitiveConversions::cast<uint>(PrimitiveConversions::cast<UI>(ufive))); } +TEST(PrimitiveConversionsTest, round_trip_int_constexpr) { + constexpr int sfive = 5; + constexpr int mfive = -5; + constexpr uint ufive = 5u; + + typedef PrimitiveConversionsTestSupport::Signed<int>::type SI; + typedef PrimitiveConversionsTestSupport::Unsigned<int>::type UI; + + { + constexpr SI i = PrimitiveConversions::cast<SI>(sfive); + constexpr int r = PrimitiveConversions::cast<int>(i); + EXPECT_EQ(sfive, r); + } + + { + constexpr UI i = PrimitiveConversions::cast<UI>(sfive); + constexpr int r = PrimitiveConversions::cast<int>(i); + EXPECT_EQ(sfive, r); + } + + { + constexpr SI i = PrimitiveConversions::cast<SI>(mfive); + constexpr int r = PrimitiveConversions::cast<int>(i); + EXPECT_EQ(mfive, r); + } + + { + constexpr UI i = PrimitiveConversions::cast<UI>(mfive); + constexpr int r = PrimitiveConversions::cast<int>(i); + EXPECT_EQ(mfive, r); + } + + { + constexpr SI i = PrimitiveConversions::cast<SI>(ufive); + constexpr uint r = PrimitiveConversions::cast<uint>(i); + EXPECT_EQ(ufive, r); + } + + { + constexpr UI i = PrimitiveConversions::cast<UI>(ufive); + constexpr uint r = PrimitiveConversions::cast<uint>(i); + EXPECT_EQ(ufive, r); + } +} + TEST(PrimitiveConversionsTest, round_trip_float) { float ffive = 5.0f; double dfive = 5.0; diff --git a/test/hotspot/gtest/runtime/test_arguments.cpp b/test/hotspot/gtest/runtime/test_arguments.cpp index b6121ba3aba..81bae6c468a 100644 --- a/test/hotspot/gtest/runtime/test_arguments.cpp +++ b/test/hotspot/gtest/runtime/test_arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,7 +153,7 @@ static intx calc_expected(julong small_xss_input) { assert(small_xss_input <= max_julong / 2, "Sanity"); // Match code in arguments.cpp - julong julong_ret = align_up_(small_xss_input, K) / K; + julong julong_ret = align_up(small_xss_input, K) / K; assert(julong_ret <= (julong)max_intx, "Overflow: " JULONG_FORMAT, julong_ret); return (intx)julong_ret; } diff --git a/test/hotspot/gtest/utilities/test_align.cpp b/test/hotspot/gtest/utilities/test_align.cpp index e522acc5f01..1097dd6c4f7 100644 --- a/test/hotspot/gtest/utilities/test_align.cpp +++ b/test/hotspot/gtest/utilities/test_align.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * 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,21 +25,82 @@ #include "utilities/align.hpp" #include "utilities/formatBuffer.hpp" #include "utilities/globalDefinitions.hpp" -#include "unittest.hpp" - #include <limits> +#include "unittest.hpp" // A few arbitrarily chosen values to test the align functions on. -static uint64_t values[] = {1, 3, 10, 345, 1023, 1024, 1025, 23909034, INT_MAX, uint64_t(-1) / 2, uint64_t(-1) / 2 + 100, uint64_t(-1)}; +static constexpr uint64_t values[] = {1, 3, 10, 345, 1023, 1024, 1025, 23909034, INT_MAX, uint64_t(-1) / 2, uint64_t(-1) / 2 + 100, uint64_t(-1)}; template <typename T> -static T max_alignment() { +static constexpr T max_alignment() { T max = std::numeric_limits<T>::max(); return max ^ (max >> 1); } #define log(...) SCOPED_TRACE(err_msg(__VA_ARGS__).buffer()) +struct StaticTestAlignmentsResult { + uint64_t _value; + uint64_t _alignment; + int _status; // 0: success, > 0 indicates which failure case + constexpr StaticTestAlignmentsResult(uint64_t value, uint64_t alignment, int status) : + _value(value), _alignment(alignment), _status(status) {} +}; + +// Structure copied from test_alignments runtime test (below). +template<typename T, typename A> +static constexpr StaticTestAlignmentsResult +static_test_alignments_aux(A alignment) { + using Result = StaticTestAlignmentsResult; + + for ( ; alignment > 0; alignment >>= 1) { + for (size_t i = 0; i < ARRAY_SIZE(values); ++i) { + // Test align up + uint64_t up = align_up(values[i], alignment); + if (0 < up && up < uint64_t(std::numeric_limits<T>::max())) { + T value = T(values[i]); + if (align_up(uint64_t(value), alignment) != up) { + return Result(values[i], alignment, 1); + } else if (align_up(value, alignment) < value) { + return Result(values[i], alignment, 2); + } + } + + // Test align down + uint64_t down = align_down(values[i], alignment); + if (down <= uint64_t(std::numeric_limits<T>::max())) { + T value = T(values[i]); + if (uint64_t(align_down(value, alignment)) != down) { + return Result(values[i], alignment, 3); + } else if (align_down(value, alignment) > value) { + return Result(values[i], alignment, 4); + } + } + + // Test is aligned + bool is = is_aligned(values[i], alignment); + if (values[i] <= uint64_t(std::numeric_limits<T>::max())) { + T value = T(values[i]); + if (is_aligned(value, alignment) != is) { + return Result(values[i], alignment, 5); + } + } + } + } + return Result(T(), A(), 0); +} + +template<typename T, typename A> +static void static_test_alignments() { + constexpr StaticTestAlignmentsResult result + = static_test_alignments_aux<T>(max_alignment<A>()); + + EXPECT_EQ(0, result._status) + << "value = " << result._value + << ", alignment = " << result._alignment + << ", status = " << result._status; +} + template <typename T, typename A> static void test_alignments() { log("### Test: %c" SIZE_FORMAT " " UINT64_FORMAT " : %c" SIZE_FORMAT " " UINT64_FORMAT " ###\n", @@ -54,7 +115,7 @@ static void test_alignments() { log("--- Value: " UINT64_FORMAT "\n", values[i]); // Test align up - const uint64_t up = align_up_(values[i], (uint64_t)alignment); + const uint64_t up = align_up(values[i], alignment); if (0 < up && up <= (uint64_t)std::numeric_limits<T>::max()) { log("Testing align_up: alignment: 0x" UINT64_FORMAT_X " value: 0x" UINT64_FORMAT_X " expected: 0x" UINT64_FORMAT_X "\n", (uint64_t)alignment, values[i], up); @@ -62,14 +123,12 @@ static void test_alignments() { // Check against uint64_t version ASSERT_EQ(align_up((uint64_t)value, alignment), up); - // Check inline function vs macro - ASSERT_EQ(align_up(value, alignment), align_up_(value, alignment)); // Sanity check ASSERT_GE(align_up(value, alignment), value); } // Test align down - const uint64_t down = align_down_(values[i], (uint64_t)alignment); + const uint64_t down = align_down(values[i], alignment); if (down <= (uint64_t)std::numeric_limits<T>::max()) { log("Testing align_down: alignment: 0x" UINT64_FORMAT_X " value: 0x" UINT64_FORMAT_X " expected: 0x" UINT64_FORMAT_X "\n", (uint64_t)alignment, values[i], down); @@ -77,14 +136,12 @@ static void test_alignments() { // Check against uint64_t version ASSERT_EQ((uint64_t)align_down(value, alignment), down); - // Check inline function vs macro - ASSERT_EQ(align_down(value, alignment), align_down_(value, alignment)); // Sanity check ASSERT_LE(align_down(value, alignment), value); } // Test is aligned - const bool is = is_aligned_(values[i], (uint64_t)alignment); + const bool is = is_aligned(values[i], alignment); if (values[i] <= (uint64_t)std::numeric_limits<T>::max()) { log("Testing is_aligned: alignment: 0x" UINT64_FORMAT_X " value: 0x" UINT64_FORMAT_X " expected: %s\n", (uint64_t)alignment, values[i], is ? "true" : "false"); @@ -92,14 +149,14 @@ static void test_alignments() { // Check against uint64_t version ASSERT_EQ(is_aligned(value, alignment), is); - // Check inline function vs macro - ASSERT_EQ(is_aligned(value, alignment), is_aligned_(value, alignment)); } } } + + static_test_alignments<T, A>(); } -TEST(Align, functions_and_macros) { +TEST(Align, alignments) { // Test the alignment functions with different type combinations. test_alignments<int64_t, uint8_t>(); diff --git a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp index a920351ee78..e82eea051ae 100644 --- a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp +++ b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp @@ -23,9 +23,10 @@ #include "precompiled.hpp" #include "runtime/os.hpp" -#include "unittest.hpp" #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" +#include <type_traits> +#include "unittest.hpp" static ::testing::AssertionResult testPageAddress( const char* expected_addr_expr, @@ -192,7 +193,7 @@ TEST(globalDefinitions, byte_size_in_exact_unit) { #define EXPECT_EQ_LOG2(fn, type) \ { \ int limit = sizeof (type) * BitsPerByte; \ - if (IsSigned<type>::value) { \ + if (std::is_signed<type>::value) { \ EXPECT_EQ(limit - 1, fn(std::numeric_limits<type>::min())); \ EXPECT_EQ(limit - 1, fn((type)-1)); \ limit--; \ diff --git a/test/hotspot/gtest/utilities/test_population_count.cpp b/test/hotspot/gtest/utilities/test_population_count.cpp index a5320817ac2..4ed6513ec13 100644 --- a/test/hotspot/gtest/utilities/test_population_count.cpp +++ b/test/hotspot/gtest/utilities/test_population_count.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * 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,6 +27,7 @@ #include "utilities/population_count.hpp" #include "utilities/powerOfTwo.hpp" #include "utilities/globalDefinitions.hpp" +#include <limits> #include "unittest.hpp" #define BITS_IN_BYTE_ARRAY_SIZE 256 @@ -51,8 +52,8 @@ const uint8_t test_popcnt_bitsInByte[BITS_IN_BYTE_ARRAY_SIZE] = { }; template <typename T> -void sparse() { - const T max_val = max_value<T>(); +static void sparse() { + const T max_val = std::numeric_limits<T>::max(); // Step through the entire input range from a random starting point, // verify population_count return values against the lookup table @@ -95,4 +96,4 @@ TEST(population_count, sparse32) { } TEST(population_count, sparse64) { sparse<uint64_t>(); -} \ No newline at end of file +} diff --git a/test/hotspot/gtest/utilities/test_powerOfTwo.cpp b/test/hotspot/gtest/utilities/test_powerOfTwo.cpp index 795918d144f..54802a37b7b 100644 --- a/test/hotspot/gtest/utilities/test_powerOfTwo.cpp +++ b/test/hotspot/gtest/utilities/test_powerOfTwo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,57 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/powerOfTwo.hpp" +#include <limits> +#include <type_traits> #include "unittest.hpp" -template <typename T> T max_pow2() { - T max_val = max_value<T>(); +template <typename T> static constexpr T max_pow2() { + T max_val = std::numeric_limits<T>::max(); return max_val - (max_val >> 1); } +struct StaticTestIsPowerOf2Result { + uint64_t _value; + int _status; // 0: success, > 0 indicates which failure case + constexpr StaticTestIsPowerOf2Result(uint64_t value, int status) : + _value(value), _status(status) {} +}; + +// Structure copied from test_is_power_of_2 runtime test (below). +template<typename T> +static constexpr StaticTestIsPowerOf2Result static_test_is_power_of_2_aux(T v) { + using Result = StaticTestIsPowerOf2Result; + for ( ; v > 0; v >>= 1) { + if (!is_power_of_2(v)) { + return Result(v, 1); + } else if ((v > 2) && is_power_of_2(T(v - 1))) { + return Result(v, 2); + } else if ((v > 1) && is_power_of_2(T(v + 1))) { + return Result(v, 3); + } + } + return Result(v, 0); +} + +template<typename T> +static void static_test_is_power_of_2() { + constexpr StaticTestIsPowerOf2Result result + = static_test_is_power_of_2_aux(max_pow2<T>()); + + EXPECT_EQ(0, result._status) + << "value = " << result._value << ", status = " << result._status; +} + template <typename T> static void test_is_power_of_2() { EXPECT_FALSE(is_power_of_2(T(0))); EXPECT_FALSE(is_power_of_2(~T(0))); - if (IsSigned<T>::value) { - EXPECT_FALSE(is_power_of_2(std::numeric_limits<T>::min())); - } + static_assert(!is_power_of_2(T(0)), ""); + static_assert(!is_power_of_2(~T(0)), ""); + + // Should be false regardless of whether T is signed or unsigned. + EXPECT_FALSE(is_power_of_2(std::numeric_limits<T>::min())); + static_assert(!is_power_of_2(std::numeric_limits<T>::min()), ""); // Test true for (T i = max_pow2<T>(); i > 0; i = (i >> 1)) { @@ -54,6 +91,8 @@ template <typename T> static void test_is_power_of_2() { for (T i = max_pow2<T>(); i > 1; i = (i >> 1)) { EXPECT_FALSE(is_power_of_2(i + 1)) << "value = " << T(i + 1); } + + static_test_is_power_of_2<T>(); } TEST(power_of_2, is_power_of_2) { diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 6fb0bcbde76..2cb5991b41d 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -82,6 +82,7 @@ gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64 # :hotspot_runtime +runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java 8253081 generic-all runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64 runtime/ReservedStack/ReservedStackTest.java 8231031 generic-all containers/docker/TestMemoryAwareness.java 8250984 linux-5.4.0-1019-oracle diff --git a/test/hotspot/jtreg/gc/z/TestUncommit.java b/test/hotspot/jtreg/gc/z/TestUncommit.java index 17cb65dda6d..7b3374c2dfe 100644 --- a/test/hotspot/jtreg/gc/z/TestUncommit.java +++ b/test/hotspot/jtreg/gc/z/TestUncommit.java @@ -68,12 +68,12 @@ private static void reclaim() { private static void test(int objectSize) throws Exception { final var beforeAlloc = capacity(); + final var timeBeforeAlloc = System.nanoTime(); // Allocate memory log("Allocating"); allocate(objectSize); - final var timeAfterAlloc = System.nanoTime(); final var afterAlloc = capacity(); // Reclaim memory @@ -87,7 +87,7 @@ private static void test(int objectSize) throws Exception { log("Uncommit started"); final var timeUncommitStart = System.nanoTime(); - final var actualDelay = (timeUncommitStart - timeAfterAlloc) / 1_000_000; + final var actualDelay = (timeUncommitStart - timeBeforeAlloc) / 1_000_000; log("Waiting for uncommit to complete"); while (capacity() > beforeAlloc) { diff --git a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java index ed8709cda65..1d84f4aaf9c 100644 --- a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java +++ b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java @@ -28,12 +28,15 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management + * @compile ../modules/CompilerUtils.java * @run driver CheckForProperDetailStackTrace */ import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -49,6 +52,11 @@ * through this test and update it accordingly. */ public class CheckForProperDetailStackTrace { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String TEST_CLASSES = System.getProperty("test.classes"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get(TEST_CLASSES, "mods"); /* The stack trace we look for by default. Note that :: has been replaced by .* to make sure it matches even if the symbol is not unmangled. @@ -83,11 +91,24 @@ public class CheckForProperDetailStackTrace { private static String expectedSymbol = "locked_create_entry"; public static void main(String args[]) throws Exception { + boolean compiled; + // Compile module jdk.test declaration + compiled = CompilerUtils.compile( + SRC_DIR.resolve("jdk.test"), + MODS_DIR.resolve("jdk.test")); + if (!compiled) { + throw new RuntimeException("Test failed to compile module jdk.test"); + } + + // If modules in the system image have been archived in CDS, they will not be + // created again at run time. Explicitly use an external module to make sure + // we have a runtime-defined ModuleEntry ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", "-XX:NativeMemoryTracking=detail", "-XX:+PrintNMTStatistics", - "-version"); + "-p", MODS_DIR.toString(), + "-m", "jdk.test/test.Main"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/runtime/NMT/src/jdk.test/module-info.java b/test/hotspot/jtreg/runtime/NMT/src/jdk.test/module-info.java new file mode 100644 index 00000000000..0afe2ab71f7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/NMT/src/jdk.test/module-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.test { +} diff --git a/test/hotspot/jtreg/runtime/NMT/src/jdk.test/test/Main.java b/test/hotspot/jtreg/runtime/NMT/src/jdk.test/test/Main.java new file mode 100644 index 00000000000..52168d73b78 --- /dev/null +++ b/test/hotspot/jtreg/runtime/NMT/src/jdk.test/test/Main.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 test; + +public class Main { + public static void main(String[] args) throws Exception { + System.out.println("jdk.test/test/Main: hello"); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/PrimitiveClassMirrors.java b/test/hotspot/jtreg/runtime/cds/PrimitiveClassMirrors.java new file mode 100644 index 00000000000..50f769cd50d --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/PrimitiveClassMirrors.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8244778 + * @summary Make sure the archived mirrors of the primitive classes have the proper module (java.base) + * @requires vm.cds + * @library /test/lib + * @run driver PrimitiveClassMirrors + */ + +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; + +public class PrimitiveClassMirrors { + public static void main(String[] args) throws Exception { + CDSOptions opts = new CDSOptions(); + + CDSTestUtils.createArchiveAndCheck(opts); + opts.setUseVersion(false); + opts.addSuffix("-Xlog:cds=warning", "PrimitiveClassMirrors$TestApp"); + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + out.shouldHaveExitValue(0); + + // The test should have same results if CDS is turned off + opts.setXShareMode("off"); + OutputAnalyzer out2 = CDSTestUtils.runWithArchive(opts); + out2.shouldHaveExitValue(0); + } + + static class TestApp { + public static void main(String args[]) throws Exception { + Class classes[] = { + int.class, + float.class, + double.class, + byte.class, + boolean.class, + char.class, + long.class, + short.class, + void.class, + + int[].class, + float[].class, + double[].class, + byte[].class, + boolean[].class, + char[].class, + long[].class, + short[].class, + }; + + for (Class c : classes) { + test(c); + } + } + } + + static void test(Class c) throws Exception { + Module m = c.getModule(); + boolean unexpected = (m == null || !("java.base".equals(m.getName()))); + System.out.println("Module for " + c + " = " + m + (unexpected ? " *** Error" : "")); + if (unexpected) { + throw new RuntimeException("Unexpected: " + m); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java b/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java new file mode 100644 index 00000000000..efaa18b9734 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8244778 + * @summary Make sure that the ServicesCatalogs for boot/platform/app loaders are properly archived. + * @requires vm.cds + * @modules java.naming + * @library /test/lib + * @run driver ServiceLoaderTest + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.spi.ToolProvider; +import javax.naming.spi.InitialContextFactory; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; + +public class ServiceLoaderTest { + public static void main(String[] args) throws Exception { + CDSOptions opts = new CDSOptions(); + + CDSTestUtils.createArchiveAndCheck(opts); + + // Some mach5 tiers run with -vmoptions:-Xlog:cds=debug. This would cause the outputs to mismatch. + // Force -Xlog:cds=warning to supress the CDS logs. + opts.setUseVersion(false); + opts.addSuffix("-showversion", "-Xlog:cds=warning", "ServiceLoaderApp"); + OutputAnalyzer out1 = CDSTestUtils.runWithArchive(opts); + + opts.setXShareMode("off"); + OutputAnalyzer out2 = CDSTestUtils.runWithArchive(opts); + + compare(out1, out2); + } + + static void compare(OutputAnalyzer out1, OutputAnalyzer out2) { + String[] arr1 = splitLines(out1); + String[] arr2 = splitLines(out2); + + int max = arr1.length > arr2.length ? arr1.length : arr2.length; + for (int i = 0; i < max; i++) { + if (i >= arr1.length) { + mismatch(i, "<EOF>", arr2[i]); + } + if (i >= arr2.length) { + mismatch(i, arr1[i], "<EOF>"); + } + if (!arr1[i].equals(arr2[i])) { + mismatch(i, arr1[i], arr2[i]); + } + } + } + + static String[] splitLines(OutputAnalyzer out) { + return out.getStdout().split("\n"); + } + + static void mismatch(int i, String s1, String s2) { + System.out.println("Mismatched line: " + i); + System.out.println("cds on : " + s1); + System.out.println("cds off: " + s2); + throw new RuntimeException("Mismatched line " + i + ": \"" + s1 + "\" vs \"" + s2 + "\""); + } +} + +class ServiceLoaderApp { + public static void main(String args[]) throws Exception { + doTest(ToolProvider.class); + doTest(InitialContextFactory.class); + } + + static void doTest(Class c) throws Exception { + System.out.println("============================================================"); + System.out.println("Testing : " + c.getName()); + System.out.println("============================================================"); + + print_loader("default", ServiceLoader.load(c)); + print_loader("null loader", ServiceLoader.load(c, null)); + print_loader("platform loader", ServiceLoader.load(c, ServiceLoaderApp.class.getClassLoader().getParent())); + print_loader("system loader", ServiceLoader.load(c, ServiceLoaderApp.class.getClassLoader())); + } + + static void print_loader(String testCase, ServiceLoader loader) throws Exception { + System.out.println("[TEST CASE] " + testCase); + System.out.println("[svcloader] " + asString(loader)); + Iterator it = loader.iterator(); + ArrayList<String> list = new ArrayList<>(); + while (it.hasNext()) { + list.add(asString(it.next().toString())); + } + Collections.sort(list); + for (String s : list) { + System.out.println(s); + } + } + + static String asString(Object o) { + String s = o.toString(); + int n = s.indexOf("@"); + if (n >= 0) { + s = s.substring(0, n); + } + return s; + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java b/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java index 97b23507c9b..82acc8fb3cc 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,7 @@ public static void main(String[] args) throws Exception { TestCommon.run( "-verbose:class", "-cp", appJar, + "-Xlog:cds", "-Djava.system.class.loader=TestClassLoader", "ReportMyLoader") .assertNormalExit("ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@", //<-this is still printed because TestClassLoader simply delegates to Launcher$AppLoader, but ... @@ -80,6 +81,7 @@ public static void main(String[] args) throws Exception { .assertNormalExit(output -> { output.shouldMatch(".class,load. TestClassLoader source: file:"); output.shouldMatch(".class,load. ReportMyLoader source: file:.*" + jarFileName); + output.shouldContain("full module graph: disabled due to incompatible property: java.system.class.loader="); }); // (3) Try to change the java.system.class.loader programmatically after diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/NewModuleFinderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/NewModuleFinderTest.java new file mode 100644 index 00000000000..93c50b2a459 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/NewModuleFinderTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8244778 + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @run driver NewModuleFinderTest + * @summary Make sure the archived module graph can co-exist with modules that are + * dynamically defined at runtime using the ModuleFinder API. + */ + +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class NewModuleFinderTest { + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path SRC_DIR = Paths.get(TEST_SRC, "modulepath/src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String TEST_MODULE = "com.simple"; + + // the module main class + private static final String MAIN_CLASS = "com.simple.Main"; + + private static final Set<String> modules = Set.of(TEST_MODULE); + + public static void buildTestModule() throws Exception { + // javac -d mods/$TESTMODULE --module-path MOD_DIR modulepath/src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE), + MODS_DIR.resolve(TEST_MODULE), + MODS_DIR.toString()); + } + + public static void main(String... args) throws Exception { + // compile the modules and create the modular jar files + buildTestModule(); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:cds", + "-Xlog:module=debug", + "NewModuleFinderTest$Helper"); + OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "exec"); + out.shouldHaveExitValue(0); + out.shouldContain("define_module(): creation of module: com.simple,"); + } + + static class Helper { + public static void main(String... args) { + ModuleFinder finder = ModuleFinder.of(MODS_DIR); + Configuration parent = ModuleLayer.boot().configuration(); + Configuration cf = parent.resolveAndBind(ModuleFinder.of(), + finder, + modules); + + ClassLoader scl = ClassLoader.getSystemClassLoader(); + ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl); + + Module m1 = layer.findModule(TEST_MODULE).get(); + System.out.println("Module = " + m1); + if (m1 != null) { + System.out.println("Success"); + } else { + throw new RuntimeException("Module should not be null"); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraph.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraph.java new file mode 100644 index 00000000000..c42b922b340 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraph.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8249276 + * @summary Make sure that archived module graph is not loaded if critical classes have been redefined. + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @requires vm.cds + * @requires vm.flavor != "minimal" + * @modules java.instrument + * @run driver RedefineClassesInModuleGraph + */ + +import jdk.test.lib.process.OutputAnalyzer; + +public class RedefineClassesInModuleGraph { + public static String appClasses[] = { + RedefineClassesInModuleGraphApp.class.getName(), + }; + public static String agentClasses[] = { + RedefineClassesInModuleGraphAgent.class.getName(), + RedefineClassesInModuleGraphTransformer.class.getName(), + }; + + private static final String MANIFEST = + "Manifest-Version: 1.0\n" + + "Premain-Class: RedefineClassesInModuleGraphAgent\n" + + "Can-Retransform-Classes: true\n" + + "Can-Redefine-Classes: true\n"; + + public static void main(String[] args) throws Throwable { + String agentJar = + ClassFileInstaller.writeJar("RedefineClassesInModuleGraphAgent.jar", + ClassFileInstaller.Manifest.fromString(MANIFEST), + agentClasses); + + String appJar = + ClassFileInstaller.writeJar("RedefineClassesInModuleGraphApp.jar", appClasses); + + TestCommon.testDump(appJar, agentClasses); + + TestCommon.run( + "-cp", appJar, + "-javaagent:" + agentJar, + RedefineClassesInModuleGraphApp.class.getName()) + .assertNormalExit(); + } +} + diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphAgent.java new file mode 100644 index 00000000000..f4a6d38a8fb --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphAgent.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Instrumentation; + +public class RedefineClassesInModuleGraphAgent { + private static Instrumentation savedInstrumentation; + + public static void premain(String agentArguments, Instrumentation instrumentation) { + instrumentation.addTransformer(new RedefineClassesInModuleGraphTransformer(), /*canRetransform=*/true); + savedInstrumentation = instrumentation; + } + + public static Instrumentation getInstrumentation() { + return savedInstrumentation; + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphApp.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphApp.java new file mode 100644 index 00000000000..0cc54d1f1e8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphApp.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 RedefineClassesInModuleGraphApp { + public static void main(String args[]) { + Module m = Object.class.getModule(); + ModuleLayer ml = m.getLayer(); + System.out.println(m); + System.out.println(ml); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphTransformer.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphTransformer.java new file mode 100644 index 00000000000..1b77f69c38c --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraphTransformer.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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; + +public class RedefineClassesInModuleGraphTransformer implements ClassFileTransformer { + public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined, + ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException { + System.out.println("transforming " + name); + + if (name.equals("java/lang/Module") || + name.equals("java/lang/ModuleLayer") || + name.equals("java/lang/module/ResolvedModule")) { + throw new RuntimeException("Classes used by the module graph should never be transformed by Java agent"); + } + return null; + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java index 836f0d444e6..f16982c7b1e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java @@ -24,7 +24,7 @@ /** * @test - * @requires vm.cds & !vm.jvmci + * @requires vm.cds & !vm.graal.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @run driver OptimizeModuleHandlingTest * @summary test module path changes for optimization of @@ -63,8 +63,8 @@ public class OptimizeModuleHandlingTest { private static String CLASS_FOUND_MESSAGE = "com.foos.Test found"; private static String CLASS_NOT_FOUND_MESSAGE = "java.lang.ClassNotFoundException: com.foos.Test"; - private static String OPTIMIZE_ENABLED = "Using optimized module handling enabled"; - private static String OPTIMIZE_DISABLED = "Using optimized module handling disabled"; + private static String OPTIMIZE_ENABLED = "optimized module handling: enabled"; + private static String OPTIMIZE_DISABLED = "optimized module handling: disabled"; private static String MAIN_FROM_JAR = "class,load.*com.bars.Main.*[.]jar"; private static String MAIN_FROM_CDS = "class,load.*com.bars.Main.*shared objects file"; private static String TEST_FROM_JAR = "class,load.*com.foos.Test.*[.]jar"; diff --git a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClasses.java b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClasses.java index e70021c4ef8..84c17c331f3 100644 --- a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClasses.java +++ b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,8 @@ public void process(String args[]) throws Throwable { .setXShareMode("dump") .setArchiveName(ReplaceCriticalClasses.class.getName() + ".jsa") .setUseVersion(false) - .addSuffix("-showversion"); + .addSuffix("-showversion") + .addSuffix("-Xlog:cds"); CDSTestUtils.run(opts).assertNormalExit(""); launchChildProcesses(getTests()); @@ -80,6 +81,8 @@ public String[] getTests() { "-early -notshared java/lang/String", "-early -notshared java/lang/Cloneable", "-early -notshared java/io/Serializable", + "-early -notshared java/lang/Module", + "-early -notshared java/lang/ModuleLayer", // CDS should not be disabled -- these critical classes cannot be replaced because // JvmtiExport::early_class_hook_env() is false. @@ -87,13 +90,8 @@ public String[] getTests() { "java/lang/String", "java/lang/Cloneable", "java/io/Serializable", - - /* Try to replace classes that are used by the archived subgraph graphs. - The following test cases are in ReplaceCriticalClassesForSubgraphs.java. - "-early -notshared -subgraph java/lang/module/ResolvedModule jdk.internal.module.ArchivedModuleGraph", - "-early -notshared -subgraph java/lang/Long java.lang.Long$LongCache", - "-subgraph java/lang/Long java.lang.Long$LongCache", - */ + "java/lang/Module", + "java/lang/ModuleLayer", // Replace classes that are loaded after JVMTI_PHASE_PRIMORDIAL. It's OK to replace // such @@ -116,12 +114,13 @@ static void launchChildProcesses(String tests[]) throws Throwable { static void launchChild(String args[]) throws Throwable { if (args.length < 1) { - throw new RuntimeException("Invalid test case. Should be <-early> <-subgraph> <-notshared> klassName subgraphKlass"); + throw new RuntimeException("Invalid test case. Should be <-early> <-subgraph> <-notshared> <-nowhitebox> klassName subgraphKlass"); } String klassName = null; String subgraphKlass = null; String early = ""; boolean subgraph = false; + boolean whitebox = true; String shared = "-shared"; for (int i=0; i<args.length-1; i++) { @@ -130,6 +129,8 @@ static void launchChild(String args[]) throws Throwable { early = "-early,"; } else if (opt.equals("-subgraph")) { subgraph = true; + } else if (opt.equals("-nowhitebox")) { + whitebox = false; } else if (opt.equals("-notshared")) { shared = opt; } else { @@ -166,10 +167,11 @@ static void launchChild(String args[]) throws Throwable { .addSuffix("-showversion", "-Xlog:cds", "-XX:+UnlockDiagnosticVMOptions", - agent, - "-XX:+WhiteBoxAPI", - "-Xbootclasspath/a:" + ClassFileInstaller.getJarPath("whitebox.jar")); - + agent); + if (whitebox) { + opts.addSuffix("-XX:+WhiteBoxAPI", + "-Xbootclasspath/a:" + ClassFileInstaller.getJarPath("whitebox.jar")); + } if (subgraph) { opts.addSuffix("-Xlog:cds,cds+heap"); } @@ -191,6 +193,8 @@ static void launchChild(String args[]) throws Throwable { if (expectShared) { if (!out.getOutput().contains("UseSharedSpaces: Unable to map at required address in java heap")) { out.shouldContain(subgraphInit); + // If the subgraph is successfully initialized, the specified shared class must not be rewritten. + out.shouldNotContain("Rewriting done."); } } else { out.shouldNotContain(subgraphInit); @@ -200,15 +204,19 @@ static void launchChild(String args[]) throws Throwable { } static void testInChild(boolean shouldBeShared, Class klass) { - WhiteBox wb = WhiteBox.getWhiteBox(); + try { + WhiteBox wb = WhiteBox.getWhiteBox(); - if (shouldBeShared && !wb.isSharedClass(klass)) { - throw new RuntimeException(klass + " should be shared but but actually is not."); - } - if (!shouldBeShared && wb.isSharedClass(klass)) { - throw new RuntimeException(klass + " should not be shared but actually is."); + if (shouldBeShared && !wb.isSharedClass(klass)) { + throw new RuntimeException(klass + " should be shared but but actually is not."); + } + if (!shouldBeShared && wb.isSharedClass(klass)) { + throw new RuntimeException(klass + " should not be shared but actually is."); + } + System.out.println("wb.isSharedClass(" + klass + "): " + wb.isSharedClass(klass) + " == " + shouldBeShared); + } catch (UnsatisfiedLinkError e) { + System.out.println("WhiteBox is disabled -- because test has -nowhitebox"); } - System.out.println("wb.isSharedClass(klass): " + wb.isSharedClass(klass) + " == " + shouldBeShared); String strings[] = { // interned strings from j.l.Object diff --git a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java index 68efc0af1de..fe081b49078 100644 --- a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java +++ b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,10 +40,21 @@ public static void main(String args[]) throws Throwable { public String[] getTests() { String tests[] = { - // Try to replace classes that are used by the archived subgraph graphs. + // Try to replace classes that are used by the archived subgraph graphs. (CDS should be disabled) "-early -notshared -subgraph java/lang/module/ResolvedModule jdk.internal.module.ArchivedModuleGraph", "-early -notshared -subgraph java/lang/Long java.lang.Long$LongCache", + + // CDS should not be disabled -- these critical classes cannot be replaced because + // JvmtiExport::early_class_hook_env() is false. + "-subgraph java/lang/module/ResolvedModule jdk.internal.module.ArchivedModuleGraph", "-subgraph java/lang/Long java.lang.Long$LongCache", + + // Tests for archived full module graph. We cannot use whitebox, which requires appending to bootclasspath. + // VM will disable full module graph if bootclasspath is appended. + "-nowhitebox -early -notshared -subgraph java/lang/Module jdk.internal.module.ArchivedBootLayer", + "-nowhitebox -early -notshared -subgraph java/lang/ModuleLayer jdk.internal.module.ArchivedBootLayer", + "-nowhitebox -subgraph java/lang/Module jdk.internal.module.ArchivedBootLayer", + "-nowhitebox -subgraph java/lang/ModuleLayer jdk.internal.module.ArchivedBootLayer", }; return tests; } diff --git a/test/hotspot/jtreg/runtime/logging/ModulesTest.java b/test/hotspot/jtreg/runtime/logging/ModulesTest.java index 20962e1f103..6ebb73cf20f 100644 --- a/test/hotspot/jtreg/runtime/logging/ModulesTest.java +++ b/test/hotspot/jtreg/runtime/logging/ModulesTest.java @@ -34,13 +34,18 @@ import jdk.test.lib.process.ProcessTools; public class ModulesTest { + // If modules in the system image have been archived in CDS, no Modules will + // be dynamically created at runtime. Disable CDS so all of the expected messages + // are printed. + private static String XSHARE_OFF = "-Xshare:off"; + public static void main(String[] args) throws Exception { - testModuleTrace("-Xlog:module=trace", "-version"); - testModuleLoad("-Xlog:module+load", "-version"); - testModuleUnload("-Xlog:module+unload", "-version"); + testModuleTrace("-Xlog:module=trace", XSHARE_OFF, "-version"); + testModuleLoad("-Xlog:module+load", XSHARE_OFF, "-version"); + testModuleUnload("-Xlog:module+unload", XSHARE_OFF, "-version"); // same as -Xlog:module+load -Xlog:module+unload - testModuleLoad("-verbose:module", "-version"); + testModuleLoad("-verbose:module", XSHARE_OFF, "-version"); } static void testModuleTrace(String... args) throws Exception { diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetLocalVariable/libGetLocalWithoutSuspendTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/GetLocalVariable/libGetLocalWithoutSuspendTest.cpp index 5ae223aed5d..fe5e8c992fc 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/GetLocalVariable/libGetLocalWithoutSuspendTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/GetLocalVariable/libGetLocalWithoutSuspendTest.cpp @@ -154,7 +154,7 @@ void test_GetLocalObject(jvmtiEnv* jvmti, JNIEnv* env, int depth) { jobject obj; char* errMsg; - printf("AGENT: calling GetLocalObject()\n"); + printf("AGENT: calling GetLocalObject() with depth %d\n", depth); err = jvmti->GetLocalObject(target_thread, depth, 0, &obj); errMsg = GetErrorMessage(jvmti, err); printf("AGENT: GetLocalObject() result code %s (%d)\n", errMsg != NULL ? errMsg : "N/A", err); @@ -166,9 +166,13 @@ void test_GetLocalObject(jvmtiEnv* jvmti, JNIEnv* env, int depth) { // If the target thread wins the race we can get errors because we // don't find a frame at the given depth or we find a non-java frame // there (e.g. native frame). This is expected. + // JVMTI_ERROR_INVALID_SLOT can occur also because the target thread is + // running and the GetLocalObject() call might coincidentally refer to the + // frame of a static method without parameters. if (err != JVMTI_ERROR_NONE && err != JVMTI_ERROR_NO_MORE_FRAMES && - err != JVMTI_ERROR_OPAQUE_FRAME) { + err != JVMTI_ERROR_OPAQUE_FRAME && + err != JVMTI_ERROR_INVALID_SLOT) { ShowErrorMessage(jvmti, err, "AgentThreadLoop: error in JVMTI GetLocalObject"); env->FatalError("AgentThreadLoop: error in JVMTI GetLocalObject\n"); } @@ -260,7 +264,7 @@ AgentThreadLoop(jvmtiEnv * jvmti, JNIEnv* env, void * arg) { // It notifies the agent to do the GetLocalObject() call and then races // it to make its stack not walkable by returning from the native call. JNIEXPORT void JNICALL -Java_GetLocalWithoutSuspendTest_notifyAgentToGetLocal(JNIEnv *env, jclass cls, jint depth, jlong waitCycles) { +Java_GetLocalWithoutSuspendTest_notifyAgentToGetLocal(JNIEnv *env, jclass cls, jint depth, jint waitCycles) { monitor_enter(jvmti, env, AT_LINE); // Set depth_for_get_local and notify agent that the target thread is ready for the GetLocalObject() call diff --git a/test/hotspot/jtreg/test_env.sh b/test/hotspot/jtreg/test_env.sh deleted file mode 100644 index 10b4630df1e..00000000000 --- a/test/hotspot/jtreg/test_env.sh +++ /dev/null @@ -1,212 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please 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 Environment script was written to capture typically used environment -# setup for a given shell test. -# - -# TESTJAVA can be a JDK or JRE. If JRE you need to set COMPILEJAVA -if [ "${TESTJAVA}" = "" ] -then - echo "TESTJAVA not set. Test cannot execute. Failed." - exit 1 -fi -echo "TESTJAVA=${TESTJAVA}" - -# COMPILEJAVA requires a JDK, some shell test use javac,jar,etc -if [ "${COMPILEJAVA}" = "" ] -then - echo "COMPILEJAVA not set. Using TESTJAVA as default" - COMPILEJAVA=${TESTJAVA} -fi -echo "COMPILEJAVA=${COMPILEJAVA}" - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASES not set. Using "." as default" - TESTCLASSES=. -fi -echo "TESTCLASSES=${TESTCLASSES}" - -TESTOPTS="${TESTVMOPTS} ${TESTJAVAOPTS}" -echo "TESTOPTS=${TESTOPTS}" - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - AIX | Darwin | Linux ) - NULL=/dev/null - PS=":" - FS="/" - RM=/bin/rm - CP=/bin/cp - MV=/bin/mv - ;; - Windows_* ) - NULL=NUL - PS=";" - FS="\\" - RM=rm - CP=cp - MV=mv - ;; - CYGWIN_* ) - NULL=/dev/null - PS=";" - FS="/" - RM=rm - CP=cp - MV=mv - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -export NULL PS FS RM CP MV -echo "NULL =${NULL}" -echo "PS =${PS}" -echo "FS =${FS}" -echo "RM =${RM}" -echo "CP =${CP}" -echo "MV =${MV}" - -# jtreg -classpathappend:<path> -JEMMYPATH=${CPAPPEND} -CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH -echo "CLASSPATH =${CLASSPATH}" - -# Current directory is scratch directory -THIS_DIR=. -echo "THIS_DIR=${THIS_DIR}" - -# Check to ensure the java defined actually works -${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -version -if [ $? != 0 ]; then - echo "Wrong TESTJAVA or TESTJAVAOPTS or TESTVMOPTS:" - echo ''$TESTJAVA'' ''$TESTJAVAOPTS'' ''$TESTVMOPTS'' - exit 1 -fi - -${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xinternalversion | sed -e 's/[(][^)]*[)]//g' -e 's/ by "[^"]*"//g' > vm_version.out 2>&1 -echo "INT_VERSION=`cat vm_version.out 2>&1`" - -VM_TYPE="unknown" -grep "Server" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_TYPE="server" -fi -grep "Client" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_TYPE="client" -fi - -VM_BITS="32" -grep "64-Bit" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_BITS="64" -fi - -VM_OS="unknown" -grep "aix" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_OS="aix" -fi -grep "bsd" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_OS="bsd" -fi -grep "linux" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_OS="linux" -fi -grep "windows" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_OS="windows" -fi - -VM_CPU="unknown" -grep "x86" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="i386" -fi -grep "amd64" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="amd64" -fi -grep "arm" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="arm" -fi -grep "ppc" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="ppc" - if [ $VM_BITS = "64" ] - then - VM_CPU="ppc64" - grep "ppc64le" vm_version.out > ${NULL} - if [ $? = 0 ] - then - VM_CPU="ppc64le" - fi - fi -fi -grep "ia64" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="ia64" -fi -grep "s390x" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="s390x" -fi -grep "aarch64" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="aarch64" -fi -grep "arm64" vm_version.out > ${NULL} -if [ $? = 0 ] -then - VM_CPU="aarch64" -fi -export VM_TYPE VM_BITS VM_OS VM_CPU -echo "VM_TYPE=${VM_TYPE}" -echo "VM_BITS=${VM_BITS}" -echo "VM_OS=${VM_OS}" -echo "VM_CPU=${VM_CPU}" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java index da9dae6377b..fcb18ed216e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java @@ -41,10 +41,10 @@ * See the bug: * 4366625 (P4/S4) multiple stack overflow causes HS crash * - * @requires (vm.opt.DeoptimizeALot != true & vm.compMode != "Xcomp") + * @requires (vm.opt.DeoptimizeALot != true & vm.compMode != "Xcomp" & vm.pageSize == 4096) * @library /vmTestbase * @build nsk.share.Terminator - * @run main/othervm/timeout=900 -Xss448K nsk.stress.stack.stack017 -eager + * @run main/othervm/timeout=900 -Xss220K nsk.stress.stack.stack017 -eager */ package nsk.stress.stack; diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 0d5c75221d7..cbae666f145 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -836,7 +836,6 @@ javax/swing/JMenuItem/4171437/bug4171437.java 8233641 macosx-all javax/swing/JMenu/4692443/bug4692443.java 8171998 macosx-all javax/swing/plaf/synth/7158712/bug7158712.java 8238720 windows-all javax/swing/plaf/basic/BasicComboPopup/JComboBoxPopupLocation/JComboBoxPopupLocation.java 8238720 windows-all -javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java 8238720 windows-all sanity/client/SwingSet/src/ToolTipDemoTest.java 8225012 windows-all,macosx-all sanity/client/SwingSet/src/ScrollPaneDemoTest.java 8225013 linux-all diff --git a/test/jdk/java/awt/ColorClass/AlphaColorTest.java b/test/jdk/java/awt/ColorClass/AlphaColorTest.java index b26bb0616f4..e3478c961fc 100644 --- a/test/jdk/java/awt/ColorClass/AlphaColorTest.java +++ b/test/jdk/java/awt/ColorClass/AlphaColorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,8 +84,8 @@ public void paint(Graphics g) { Color color = new Color(255, 255, 255, 127); frame.add("Center", new AlphaColorTest(color)); frame.setUndecorated(true); - frame.setLocationRelativeTo(null); frame.pack(); + frame.setLocationRelativeTo(null); frame.setVisible(true); } } diff --git a/test/jdk/java/lang/annotation/typeAnnotations/TypeVariableBoundParameterIndex.java b/test/jdk/java/lang/annotation/typeAnnotations/TypeVariableBoundParameterIndex.java new file mode 100644 index 00000000000..12dc344a002 --- /dev/null +++ b/test/jdk/java/lang/annotation/typeAnnotations/TypeVariableBoundParameterIndex.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8202473 + * @summary Annotations on type variables with multiple bounds should be placed on their respective bound + * @compile TypeVariableBoundParameterIndex.java + * @run main TypeVariableBoundParameterIndex + */ + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.TypeVariable; +import java.util.concurrent.Callable; + +/* + * A class might have multiple bounds as parameterized types with type annotations on these bounds. + * This test assures that these bound annotations are resolved correctly. + */ +public class TypeVariableBoundParameterIndex { + + public static void main(String[] args) throws Exception { + TypeVariable<?>[] variables = Sample.class.getTypeParameters(); + + for (int i = 0; i < 2; i++) { + TypeVariable<?> variable = variables[i]; + AnnotatedType[] bounds = variable.getAnnotatedBounds(); + AnnotatedType bound = bounds[0]; + AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) bound; + AnnotatedType[] actualTypeArguments = parameterizedType.getAnnotatedActualTypeArguments(); + Annotation[] annotations = actualTypeArguments[0].getAnnotations(); + if (annotations.length != 1 || annotations[0].annotationType() != TypeAnnotation.class) { + throw new AssertionError(); + } + } + + TypeVariable<?> variable = variables[2]; + AnnotatedType[] bounds = variable.getAnnotatedBounds(); + AnnotatedType bound = bounds[0]; + AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) bound; + AnnotatedType[] actualTypeArguments = parameterizedType.getAnnotatedActualTypeArguments(); + Annotation[] annotations = actualTypeArguments[0].getAnnotations(); + if (annotations.length != 0) { + throw new AssertionError(); + } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + @interface TypeAnnotation { } + + static class Sample<T extends Callable<@TypeAnnotation ?>, S extends Callable<@TypeAnnotation ?>, U extends Callable<?>> { } +} diff --git a/test/jdk/java/lang/lang-runtime/PatternHandleTest.java b/test/jdk/java/lang/lang-runtime/PatternHandleTest.java deleted file mode 100755 index e7643c5a1dc..00000000000 --- a/test/jdk/java/lang/lang-runtime/PatternHandleTest.java +++ /dev/null @@ -1,457 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.runtime.PatternHandle; -import java.lang.runtime.PatternHandles; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import org.testng.annotations.Test; - -import static java.util.Map.entry; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNotSame; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -/** - * @test - * @run testng PatternHandleTest - * @summary Smoke tests for java.lang.runtime.Extractor - */ -@Test -public class PatternHandleTest { - - enum MatchKind { - /** Match succeeds, with a carrier object different form the target */ - MATCH_CARRIER, - /** Match succeeds, with self-carrier */ - MATCH_SELF, - /** Match succeeds, carrier provenance unknown */ - MATCH, - /** Match fails */ - NO_MATCH, - /** Match fails with a runtime exception */ - ERROR; - } - - // We have to resort to the subterfuge of laundering the tryMatch invocation - // through an ancillary object, because the only way to control the static - // signature is through the static types. So we have a bunch of invokers, - // each of which embeds different assumptions about the target type. This - // way we can test mismatches between the expected and actual types. - - interface TryMatchInvoker<T> { - Object tryMatch(MethodHandle mh, T target) throws Throwable; - } - - static final TryMatchInvoker<Object> objectInvoker = (MethodHandle mh, Object x) -> mh.invokeExact(x); - static final TryMatchInvoker<Number> numberInvoker = (MethodHandle mh, Number x) -> mh.invokeExact(x); - static final TryMatchInvoker<Integer> integerInvoker = (MethodHandle mh, Integer x) -> mh.invokeExact(x); - static final TryMatchInvoker<Integer> intInvoker = (MethodHandle mh, Integer x) -> mh.invokeExact((int) x); - static final TryMatchInvoker<String> stringInvoker = (MethodHandle mh, String x) -> mh.invokeExact(x); - static final TryMatchInvoker<List> listInvoker = (MethodHandle mh, List x) -> mh.invokeExact(x); - static final TryMatchInvoker<TestClass> testClassInvoker = (MethodHandle mh, TestClass x) -> mh.invokeExact(x); - static final TryMatchInvoker<TestClass2> testClass2Invoker = (MethodHandle mh, TestClass2 x) -> mh.invokeExact(x); - - static final Map<Class<?>, TryMatchInvoker<?>> invokers - = Map.ofEntries(entry(Object.class, objectInvoker), - entry(Number.class, numberInvoker), - entry(Integer.class, integerInvoker), - entry(int.class, intInvoker), - entry(String.class, stringInvoker), - entry(List.class, listInvoker), - entry(TestClass.class, testClassInvoker), - entry(TestClass2.class, testClass2Invoker)); - - interface Throwing { - public void run() throws Throwable; - } - - static void assertThrows(Class<? extends Throwable> exception, Throwing r) { - try { - r.run(); - fail("Expected exception: " + exception); - } - catch (Throwable t) { - if (!exception.isAssignableFrom(t.getClass())) - fail(String.format("Expected exception %s, got %s", exception, t.getClass()), t); - } - } - - static void assertMatch(MatchKind expected, - PatternHandle e, - Object target, - Object... expectedBindings) throws Throwable { - int count = e.descriptor().parameterCount(); - Object[] bindings = new Object[count]; - Object carrier; - try { - TryMatchInvoker inv = invokers.get(e.descriptor().returnType()); - // @@@ temporary hack until we break out the assert-match machinery - if (inv == null) - inv = (MethodHandle mh, Object x) -> mh.invoke(x); - // @@@ end temporary hack - carrier = inv.tryMatch(e.tryMatch(), target); - } - catch (Throwable t) { - carrier = null; - if (expected == MatchKind.ERROR) - return; - else - fail("Unexpected exception in tryMatch", t); - } - - if (carrier != null) { - for (int i = 0; i < count; i++) - bindings[i] = e.component(i).invoke(carrier); - } - - if (expected == MatchKind.NO_MATCH) - assertNull(carrier); - else { - assertNotNull(carrier); - assertEquals(bindings.length, expectedBindings.length); - for (int i = 0; i < expectedBindings.length; i++) - assertEquals(bindings[i], expectedBindings[i]); - - if (expected == MatchKind.MATCH_SELF) - assertSame(carrier, target); - else if (expected == MatchKind.MATCH_CARRIER) - assertNotSame(carrier, target); - } - } - - private static class TestClass { - static TestClass INSTANCE_A = new TestClass("foo", 3, 4L, (byte) 5); - static TestClass INSTANCE_B = new TestClass(null, 0, 0L, (byte) 0); - static TestClass INSTANCE_C = new TestClass("foo", 2, 4L, (byte) 5); - static Object[] COMPONENTS_A = new Object[] { "foo", 3, 4L, (byte) 5 }; - static Object[] COMPONENTS_B = new Object[] { null, 0, 0L, (byte) 0 }; - static Object[] COMPONENTS_C = new Object[] { "foo", 2, 4L, (byte) 5 }; - - static Map<TestClass, Object[]> INSTANCES = Map.of(INSTANCE_A, COMPONENTS_A, - INSTANCE_B, COMPONENTS_B, - INSTANCE_C, COMPONENTS_C); - - static MethodHandle MH_S, MH_I, MH_L, MH_B, MH_PRED; - static MethodHandle CONSTRUCTOR; - static MethodHandle DIGESTER; - static MethodHandle DIGESTER_PARTIAL; - static MethodType TYPE = MethodType.methodType(TestClass.class, String.class, int.class, long.class, byte.class); - static { - try { - MH_B = MethodHandles.lookup().findGetter(TestClass.class, "b", byte.class); - MH_S = MethodHandles.lookup().findGetter(TestClass.class, "s", String.class); - MH_I = MethodHandles.lookup().findGetter(TestClass.class, "i", int.class); - MH_L = MethodHandles.lookup().findGetter(TestClass.class, "l", long.class); - MH_PRED = MethodHandles.lookup().findVirtual(TestClass.class, "matches", MethodType.methodType(boolean.class)); - CONSTRUCTOR = MethodHandles.lookup().findConstructor(TestClass.class, TYPE.changeReturnType(void.class)); - DIGESTER = MethodHandles.lookup().findVirtual(TestClass.class, "digest", MethodType.methodType(Object.class, MethodHandle.class)); - DIGESTER_PARTIAL = MethodHandles.lookup().findVirtual(TestClass.class, "digestPartial", MethodType.methodType(Object.class, MethodHandle.class)); - } - catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - static MethodHandle[] COMPONENT_MHS = {TestClass.MH_S, TestClass.MH_I, TestClass.MH_L, TestClass.MH_B }; - - String s; - int i; - long l; - byte b; - - TestClass(String s, int i, long l, byte b) { - this.s = s; - this.i = i; - this.l = l; - this.b = b; - } - - TestClass copy() { - return new TestClass(s, i, l, b); - } - - boolean matches() { return s != null && s.length() == i; } - - Object digest(MethodHandle target) throws Throwable { - return target.invoke(s, i, l, b); - } - - Object digestPartial(MethodHandle target) throws Throwable { - return matches() ? target.invoke(s, i, l, b) : null; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TestClass aClass = (TestClass) o; - return i == aClass.i && - l == aClass.l && - b == aClass.b && - Objects.equals(s, aClass.s); - } - - @Override - public int hashCode() { - return Objects.hash(s, i, l, b); - } - } - - private static class TestClass2 { - static MethodHandle MH_X; - static MethodType TYPE = MethodType.methodType(TestClass2.class, Object.class); - static { - try { - MH_X = MethodHandles.lookup().findGetter(TestClass2.class, "x", Object.class); - } - catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - - Object x; - - public TestClass2(Object x) { - this.x = x; - } - } - - PatternHandle TYPE_STRING = PatternHandles.ofType(String.class); - PatternHandle TYPE_LIST = PatternHandles.ofType(List.class); - PatternHandle TYPE_INTEGER = PatternHandles.ofType(Integer.class); - PatternHandle TYPE_NUMBER = PatternHandles.ofType(Number.class); - PatternHandle TYPE_OBJECT = PatternHandles.ofType(Object.class); - PatternHandle TYPE_INT = PatternHandles.ofType(int.class); - PatternHandle TYPE_STRING_NULLABLE = PatternHandles.ofTypeNullable(String.class); - - public void testType() throws Throwable { - assertMatch(MatchKind.MATCH_SELF, TYPE_STRING, "Foo", "Foo"); - assertMatch(MatchKind.NO_MATCH, TYPE_STRING, null); - assertMatch(MatchKind.ERROR, TYPE_STRING, List.of()); - assertMatch(MatchKind.ERROR, TYPE_STRING, 3); - - assertMatch(MatchKind.MATCH_SELF, TYPE_LIST, List.of(3), List.of(3)); - assertMatch(MatchKind.MATCH_SELF, TYPE_LIST, List.of(), List.of()); - assertMatch(MatchKind.MATCH_SELF, TYPE_LIST, new ArrayList<>(), List.of()); - assertMatch(MatchKind.NO_MATCH, TYPE_LIST, null); - - assertMatch(MatchKind.MATCH_SELF, TYPE_INTEGER, 3, 3); - assertMatch(MatchKind.MATCH_SELF, TYPE_NUMBER, 3, 3); - assertMatch(MatchKind.MATCH_SELF, TYPE_OBJECT, 3, 3); - assertMatch(MatchKind.NO_MATCH, TYPE_OBJECT, null); - - assertMatch(MatchKind.ERROR, TYPE_INTEGER, 3.14f); - assertMatch(MatchKind.ERROR, TYPE_INTEGER, "foo"); - } - - public void testPrimitiveType() throws Throwable { - assertMatch(MatchKind.MATCH_SELF, TYPE_INT, 3, 3); - assertMatch(MatchKind.ERROR, TYPE_INT, 3.14f); - - PatternHandle asObject = PatternHandles.adaptTarget(TYPE_INT, Object.class); - assertMatch(MatchKind.MATCH_SELF, asObject, 3, 3); - assertMatch(MatchKind.NO_MATCH, asObject, 3.14f); - assertMatch(MatchKind.NO_MATCH, asObject, null); - - PatternHandle asInteger = PatternHandles.adaptTarget(TYPE_INT, Integer.class); - assertMatch(MatchKind.MATCH_SELF, asInteger, 3, 3); - assertMatch(MatchKind.NO_MATCH, asInteger, null); - assertMatch(MatchKind.ERROR, asInteger, 3.14f); - } - - public void testNullableType() throws Throwable { - assertMatch(MatchKind.MATCH_SELF, TYPE_STRING_NULLABLE, "Foo", "Foo"); - assertMatch(MatchKind.MATCH, TYPE_STRING_NULLABLE, null, (Object) null); - assertMatch(MatchKind.ERROR, TYPE_STRING_NULLABLE, 3); - - PatternHandle asObjectNullable = PatternHandles.adaptTarget(TYPE_STRING_NULLABLE, Object.class); - assertMatch(MatchKind.MATCH_SELF, asObjectNullable, "Foo", "Foo"); - assertMatch(MatchKind.MATCH, asObjectNullable, null, (Object) null); - assertMatch(MatchKind.NO_MATCH, asObjectNullable, 3); - } - - public void testAdapt() throws Throwable { - PatternHandle e = PatternHandles.ofTypeNullable(Number.class); - PatternHandle n = PatternHandles.adaptTarget(e, Integer.class); - PatternHandle w = PatternHandles.adaptTarget(e, Object.class); - - assertEquals(e.descriptor().returnType(), Number.class); - assertEquals(n.descriptor().returnType(), Integer.class); - assertEquals(w.descriptor().returnType(), Object.class); - - assertMatch(MatchKind.MATCH_SELF, e, 1, 1); - assertMatch(MatchKind.MATCH_SELF, n, 1, 1); - assertMatch(MatchKind.MATCH_SELF, w, 1, 1); - - assertMatch(MatchKind.MATCH_SELF, e, 3.14f, 3.14f); - assertMatch(MatchKind.ERROR, n, 3.14f); - assertMatch(MatchKind.MATCH_SELF, w, 3.14f, 3.14f); - - assertMatch(MatchKind.MATCH, e, null, (Object) null); - assertMatch(MatchKind.MATCH, n, null, (Object) null); - assertMatch(MatchKind.MATCH, w, null, (Object) null); - - e = PatternHandles.ofType(Number.class); - n = PatternHandles.adaptTarget(e, Integer.class); - w = PatternHandles.adaptTarget(e, Object.class); - - assertMatch(MatchKind.MATCH_SELF, e, 1, 1); - assertMatch(MatchKind.MATCH_SELF, n, 1, 1); - assertMatch(MatchKind.MATCH_SELF, w, 1, 1); - assertMatch(MatchKind.NO_MATCH, e, null); - assertMatch(MatchKind.NO_MATCH, n, null); - assertMatch(MatchKind.NO_MATCH, w, null); - - PatternHandle widenNarrow = PatternHandles.adaptTarget(PatternHandles.adaptTarget(TYPE_STRING, Object.class), String.class); - assertMatch(MatchKind.MATCH_SELF, widenNarrow, "Foo", "Foo"); - assertMatch(MatchKind.NO_MATCH, widenNarrow, null); - assertMatch(MatchKind.ERROR, widenNarrow, List.of()); - assertMatch(MatchKind.ERROR, widenNarrow, 3); - - PatternHandle widenNarrowNullable = PatternHandles.adaptTarget(PatternHandles.adaptTarget(TYPE_STRING_NULLABLE, Object.class), String.class); - assertMatch(MatchKind.MATCH_SELF, widenNarrowNullable, "Foo", "Foo"); - assertMatch(MatchKind.MATCH, widenNarrowNullable, null, (Object) null); - assertMatch(MatchKind.ERROR, widenNarrowNullable, List.of()); - assertMatch(MatchKind.ERROR, widenNarrowNullable, 3); - } - - public void testConstant() throws Throwable { - PatternHandle constantFoo = PatternHandles.ofConstant("foo"); - assertMatch(MatchKind.MATCH, constantFoo, "foo"); - assertMatch(MatchKind.NO_MATCH, constantFoo, "bar"); - assertMatch(MatchKind.ERROR, constantFoo, 3); - assertMatch(MatchKind.NO_MATCH, constantFoo, null); - - PatternHandle constantThree = PatternHandles.ofConstant(3); - assertMatch(MatchKind.MATCH, constantThree, 3); - assertMatch(MatchKind.NO_MATCH, constantThree, 4); - assertMatch(MatchKind.NO_MATCH, constantThree, null); - } - - public void testNullConstant() throws Throwable { - PatternHandle constantNull = PatternHandles.ofConstant(null); - assertMatch(MatchKind.MATCH, constantNull, null); - assertMatch(MatchKind.NO_MATCH, constantNull, "foo"); - assertMatch(MatchKind.NO_MATCH, constantNull, 3); - } - - public void testProjections() throws Throwable { - Map<PatternHandle, MatchKind> m - = Map.of(PatternHandles.ofLazyProjection(TestClass.class, TestClass.COMPONENT_MHS), MatchKind.MATCH_SELF, - PatternHandles.ofEagerProjection(TestClass.class, TestClass.COMPONENT_MHS), MatchKind.MATCH_CARRIER); - for (var ps : m.entrySet()) { - for (var entry : TestClass.INSTANCES.entrySet()) { - assertMatch(ps.getValue(), ps.getKey(), entry.getKey(), entry.getValue()); - } - assertMatch(MatchKind.NO_MATCH, ps.getKey(), null); - - PatternHandle asObject = PatternHandles.adaptTarget(ps.getKey(), Object.class); - for (var entry : TestClass.INSTANCES.entrySet()) - assertMatch(ps.getValue(), asObject, entry.getKey(), entry.getValue()); - assertMatch(MatchKind.NO_MATCH, asObject, null); - - PatternHandle asTestClassAgain = PatternHandles.adaptTarget(asObject, TestClass.class); - for (var entry : TestClass.INSTANCES.entrySet()) - assertMatch(ps.getValue(), asTestClassAgain, entry.getKey(), entry.getValue()); - assertMatch(MatchKind.NO_MATCH, asTestClassAgain, null); - } - } - - public void testDigest() throws Throwable { - PatternHandle e = PatternHandles.ofImperative(TestClass.TYPE, TestClass.DIGESTER); - for (var entry : TestClass.INSTANCES.entrySet()) - assertMatch(MatchKind.MATCH_CARRIER, e, entry.getKey(), entry.getValue()); - assertMatch(MatchKind.NO_MATCH, e, null); - } - - public void testDigestPartial() throws Throwable { - PatternHandle e = PatternHandles.ofImperative(TestClass.TYPE, TestClass.DIGESTER_PARTIAL); - for (var entry : TestClass.INSTANCES.entrySet()) { - if (entry.getKey().matches()) - assertMatch(MatchKind.MATCH_CARRIER, e, entry.getKey(), entry.getValue()); - else - assertMatch(MatchKind.NO_MATCH, e, entry.getKey()); - } - assertMatch(MatchKind.NO_MATCH, e, null); - } - - public void testCompose() throws Throwable { - PatternHandle e = PatternHandles.ofLazyProjection(TestClass.class, TestClass.COMPONENT_MHS); - MethodHandle mh = PatternHandles.compose(e, TestClass.CONSTRUCTOR); - TestClass target = TestClass.INSTANCE_A; - Object o = mh.invoke(target); - assertTrue(o instanceof TestClass); - assertNotSame(target, o); - assertEquals(target, o); - - assertNull(mh.invoke((Object) null)); - } - - public void testDropBindings() throws Throwable { - PatternHandle e = PatternHandles.ofEagerProjection(TestClass.class, TestClass.COMPONENT_MHS); - assertMatch(MatchKind.MATCH_CARRIER, e, TestClass.INSTANCE_A, - TestClass.COMPONENTS_A); - assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(e, 0), TestClass.INSTANCE_A, - 3, 4L, (byte) 5); - assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(e, 0, 0), TestClass.INSTANCE_A, - 3, 4L, (byte) 5); - assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(e, 3), TestClass.INSTANCE_A, - "foo", 3, 4L); - assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(e, 0, 1, 2, 3), TestClass.INSTANCE_A); - - assertThrows(IndexOutOfBoundsException.class, - () -> assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(e, -1), TestClass.INSTANCE_A, - 3, 4L, (byte) 5)); - assertThrows(IndexOutOfBoundsException.class, - () -> assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(e, 4), TestClass.INSTANCE_A, - 3, 4L, (byte) 5)); - } - - public void testNested() throws Throwable { - PatternHandle TC2 = PatternHandles.ofLazyProjection(TestClass2.class, TestClass2.MH_X); - PatternHandle TC2_STRING = PatternHandles.nested(TC2, TYPE_STRING); - PatternHandle TC2_OBJECT = PatternHandles.nested(TC2, TYPE_OBJECT); - - assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(TC2_STRING, 0), new TestClass2("foo"), - "foo"); - assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(TC2_OBJECT, 0), new TestClass2("foo"), - "foo"); - assertMatch(MatchKind.NO_MATCH, PatternHandles.dropBindings(TC2_STRING, 0), new TestClass2(List.of(3)), - "foo"); - - assertMatch(MatchKind.MATCH_CARRIER, PatternHandles.dropBindings(PatternHandles.nested(TC2, TC2_STRING), 0, 1), new TestClass2(new TestClass2("foo")), - "foo"); - } -} diff --git a/test/jdk/java/lang/lang-runtime/SwitchBootstrapsTest.java b/test/jdk/java/lang/lang-runtime/SwitchBootstrapsTest.java deleted file mode 100755 index 2915302cf3b..00000000000 --- a/test/jdk/java/lang/lang-runtime/SwitchBootstrapsTest.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (c) 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.Serializable; -import java.lang.invoke.CallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.runtime.SwitchBootstraps; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; -import jdk.test.lib.RandomFactory; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; - -/** - * @test - * @key randomness - * @library /test/lib - * @build jdk.test.lib.RandomFactory - * @run testng SwitchBootstrapsTest - */ -@Test -public class SwitchBootstrapsTest { - private final static Set<Class<?>> BOOLEAN_TYPES = Set.of(boolean.class, Boolean.class); - private final static Set<Class<?>> ALL_INT_TYPES = Set.of(int.class, short.class, byte.class, char.class, - Integer.class, Short.class, Byte.class, Character.class); - private final static Set<Class<?>> SIGNED_NON_BYTE_TYPES = Set.of(int.class, Integer.class, short.class, Short.class); - private final static Set<Class<?>> CHAR_TYPES = Set.of(char.class, Character.class); - private final static Set<Class<?>> BYTE_TYPES = Set.of(byte.class, Byte.class); - private final static Set<Class<?>> SIGNED_TYPES - = Set.of(int.class, short.class, byte.class, - Integer.class, Short.class, Byte.class); - - public static final MethodHandle BSM_BOOLEAN_SWITCH; - public static final MethodHandle BSM_INT_SWITCH; - public static final MethodHandle BSM_LONG_SWITCH; - public static final MethodHandle BSM_FLOAT_SWITCH; - public static final MethodHandle BSM_DOUBLE_SWITCH; - public static final MethodHandle BSM_STRING_SWITCH; - public static final MethodHandle BSM_ENUM_SWITCH; - public static final MethodHandle BSM_TYPE_SWITCH; - - private final static Random random = RandomFactory.getRandom(); - - static { - try { - BSM_BOOLEAN_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "booleanSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, boolean[].class)); - BSM_INT_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "intSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int[].class)); - BSM_LONG_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "longSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, long[].class)); - BSM_FLOAT_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "floatSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, float[].class)); - BSM_DOUBLE_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "doubleSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, double[].class)); - BSM_STRING_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "stringSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, String[].class)); - BSM_ENUM_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "enumSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, Class.class, String[].class)); - BSM_TYPE_SWITCH = MethodHandles.lookup().findStatic(SwitchBootstraps.class, "typeSwitch", - MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, Class[].class)); - } - catch (NoSuchMethodException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - private MethodType switchType(Class<?> target) { - return MethodType.methodType(int.class, target); - } - - private Object box(Class<?> clazz, int i) { - if (clazz == Integer.class) - return i; - else if (clazz == Short.class) - return (short) i; - else if (clazz == Character.class) - return (char) i; - else if (clazz == Byte.class) - return (byte) i; - else - throw new IllegalArgumentException(clazz.toString()); - } - - private void testBoolean(boolean... labels) throws Throwable { - Map<Class<?>, MethodHandle> mhs - = Map.of(boolean.class, ((CallSite) BSM_BOOLEAN_SWITCH.invoke(MethodHandles.lookup(), "", switchType(boolean.class), labels)).dynamicInvoker(), - Boolean.class, ((CallSite) BSM_BOOLEAN_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Boolean.class), labels)).dynamicInvoker()); - - List<Boolean> labelList = new ArrayList<>(); - for (boolean label : labels) - labelList.add(label); - - for (int i=0; i<labels.length; i++) { - assertEquals(i, (int) mhs.get(boolean.class).invokeExact((boolean) labels[i])); - assertEquals(i, (int) mhs.get(Boolean.class).invokeExact((Boolean) labels[i])); - } - - boolean[] booleans = { false, true }; - for (boolean b : booleans) { - if (!labelList.contains(b)) { - assertEquals(labels.length, mhs.get(boolean.class).invoke((boolean) b)); - assertEquals(labels.length, mhs.get(Boolean.class).invoke((boolean) b)); - } - } - - assertEquals(-1, (int) mhs.get(Boolean.class).invoke(null)); - } - - private void testInt(Set<Class<?>> targetTypes, int... labels) throws Throwable { - Map<Class<?>, MethodHandle> mhs - = Map.of(char.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(char.class), labels)).dynamicInvoker(), - byte.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(byte.class), labels)).dynamicInvoker(), - short.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(short.class), labels)).dynamicInvoker(), - int.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(int.class), labels)).dynamicInvoker(), - Character.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Character.class), labels)).dynamicInvoker(), - Byte.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Byte.class), labels)).dynamicInvoker(), - Short.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Short.class), labels)).dynamicInvoker(), - Integer.class, ((CallSite) BSM_INT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Integer.class), labels)).dynamicInvoker()); - - List<Integer> labelList = IntStream.of(labels) - .boxed() - .collect(Collectors.toList()); - - for (int i=0; i<labels.length; i++) { - // test with invokeExact - if (targetTypes.contains(char.class)) - assertEquals(i, (int) mhs.get(char.class).invokeExact((char) labels[i])); - if (targetTypes.contains(byte.class)) - assertEquals(i, (int) mhs.get(byte.class).invokeExact((byte) labels[i])); - if (targetTypes.contains(short.class)) - assertEquals(i, (int) mhs.get(short.class).invokeExact((short) labels[i])); - if (targetTypes.contains(int.class)) - assertEquals(i, (int) mhs.get(int.class).invokeExact(labels[i])); - if (targetTypes.contains(Integer.class)) - assertEquals(i, (int) mhs.get(Integer.class).invokeExact((Integer) labels[i])); - if (targetTypes.contains(Short.class)) - assertEquals(i, (int) mhs.get(Short.class).invokeExact((Short) (short) labels[i])); - if (targetTypes.contains(Byte.class)) - assertEquals(i, (int) mhs.get(Byte.class).invokeExact((Byte) (byte) labels[i])); - if (targetTypes.contains(Character.class)) - assertEquals(i, (int) mhs.get(Character.class).invokeExact((Character) (char) labels[i])); - - // and with invoke - assertEquals(i, (int) mhs.get(int.class).invoke(labels[i])); - assertEquals(i, (int) mhs.get(Integer.class).invoke(labels[i])); - } - - for (int i=-1000; i<1000; i++) { - if (!labelList.contains(i)) { - assertEquals(labels.length, mhs.get(short.class).invoke((short) i)); - assertEquals(labels.length, mhs.get(Short.class).invoke((short) i)); - assertEquals(labels.length, mhs.get(int.class).invoke(i)); - assertEquals(labels.length, mhs.get(Integer.class).invoke(i)); - if (i >= 0) { - assertEquals(labels.length, mhs.get(char.class).invoke((char)i)); - assertEquals(labels.length, mhs.get(Character.class).invoke((char)i)); - } - if (i >= -128 && i <= 127) { - assertEquals(labels.length, mhs.get(byte.class).invoke((byte)i)); - assertEquals(labels.length, mhs.get(Byte.class).invoke((byte)i)); - } - } - } - - assertEquals(-1, (int) mhs.get(Integer.class).invoke(null)); - assertEquals(-1, (int) mhs.get(Short.class).invoke(null)); - assertEquals(-1, (int) mhs.get(Byte.class).invoke(null)); - assertEquals(-1, (int) mhs.get(Character.class).invoke(null)); - } - - private void testFloat(float... labels) throws Throwable { - Map<Class<?>, MethodHandle> mhs - = Map.of(float.class, ((CallSite) BSM_FLOAT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(float.class), labels)).dynamicInvoker(), - Float.class, ((CallSite) BSM_FLOAT_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Float.class), labels)).dynamicInvoker()); - - List<Float> labelList = new ArrayList<>(); - for (float label : labels) - labelList.add(label); - - for (int i=0; i<labels.length; i++) { - assertEquals(i, (int) mhs.get(float.class).invokeExact((float) labels[i])); - assertEquals(i, (int) mhs.get(Float.class).invokeExact((Float) labels[i])); - } - - float[] someFloats = { 1.0f, Float.MIN_VALUE, 3.14f }; - for (float f : someFloats) { - if (!labelList.contains(f)) { - assertEquals(labels.length, mhs.get(float.class).invoke((float) f)); - assertEquals(labels.length, mhs.get(Float.class).invoke((float) f)); - } - } - - assertEquals(-1, (int) mhs.get(Float.class).invoke(null)); - } - - private void testDouble(double... labels) throws Throwable { - Map<Class<?>, MethodHandle> mhs - = Map.of(double.class, ((CallSite) BSM_DOUBLE_SWITCH.invoke(MethodHandles.lookup(), "", switchType(double.class), labels)).dynamicInvoker(), - Double.class, ((CallSite) BSM_DOUBLE_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Double.class), labels)).dynamicInvoker()); - - var labelList = new ArrayList<Double>(); - for (double label : labels) - labelList.add(label); - - for (int i=0; i<labels.length; i++) { - assertEquals(i, (int) mhs.get(double.class).invokeExact((double) labels[i])); - assertEquals(i, (int) mhs.get(Double.class).invokeExact((Double) labels[i])); - } - - double[] someDoubles = { 1.0, Double.MIN_VALUE, 3.14 }; - for (double f : someDoubles) { - if (!labelList.contains(f)) { - assertEquals(labels.length, mhs.get(double.class).invoke((double) f)); - assertEquals(labels.length, mhs.get(Double.class).invoke((double) f)); - } - } - - assertEquals(-1, (int) mhs.get(Double.class).invoke(null)); - } - - private void testLong(long... labels) throws Throwable { - Map<Class<?>, MethodHandle> mhs - = Map.of(long.class, ((CallSite) BSM_LONG_SWITCH.invoke(MethodHandles.lookup(), "", switchType(long.class), labels)).dynamicInvoker(), - Long.class, ((CallSite) BSM_LONG_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Long.class), labels)).dynamicInvoker()); - - List<Long> labelList = new ArrayList<>(); - for (long label : labels) - labelList.add(label); - - for (int i=0; i<labels.length; i++) { - assertEquals(i, (int) mhs.get(long.class).invokeExact((long) labels[i])); - assertEquals(i, (int) mhs.get(Long.class).invokeExact((Long) labels[i])); - } - - long[] someLongs = { 1L, Long.MIN_VALUE, Long.MAX_VALUE }; - for (long l : someLongs) { - if (!labelList.contains(l)) { - assertEquals(labels.length, mhs.get(long.class).invoke((long) l)); - assertEquals(labels.length, mhs.get(Long.class).invoke((long) l)); - } - } - - assertEquals(-1, (int) mhs.get(Long.class).invoke(null)); - } - - private void testString(String... targets) throws Throwable { - MethodHandle indy = ((CallSite) BSM_STRING_SWITCH.invoke(MethodHandles.lookup(), "", switchType(String.class), targets)).dynamicInvoker(); - List<String> targetList = Stream.of(targets) - .collect(Collectors.toList()); - - for (int i=0; i<targets.length; i++) { - String s = targets[i]; - int result = (int) indy.invoke(s); - assertEquals((s == null) ? -1 : i, result); - } - - for (String s : List.of("", "A", "AA", "AAA", "AAAA")) { - if (!targetList.contains(s)) { - assertEquals(targets.length, indy.invoke(s)); - } - } - assertEquals(-1, (int) indy.invoke(null)); - } - - private<E extends Enum<E>> void testEnum(Class<E> enumClass, String... targets) throws Throwable { - MethodHandle indy = ((CallSite) BSM_ENUM_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Enum.class), enumClass, targets)).dynamicInvoker(); - List<E> targetList = Stream.of(targets) - .map(s -> Enum.valueOf(enumClass, s)) - .collect(Collectors.toList()); - - for (int i=0; i<targets.length; i++) { - String s = targets[i]; - E e = Enum.valueOf(enumClass, s); - int result = (int) indy.invoke(e); - assertEquals((s == null) ? -1 : i, result); - } - - for (E e : enumClass.getEnumConstants()) { - int index = (int) indy.invoke(e); - if (targetList.contains(e)) - assertEquals(e.name(), targets[index]); - else - assertEquals(targets.length, index); - } - - assertEquals(-1, (int) indy.invoke(null)); - } - - public void testBoolean() throws Throwable { - testBoolean(new boolean[0]); - testBoolean(false); - testBoolean(true); - testBoolean(false, true); - } - - public void testInt() throws Throwable { - testInt(ALL_INT_TYPES, 8, 6, 7, 5, 3, 0, 9); - testInt(ALL_INT_TYPES, 1, 2, 4, 8, 16); - testInt(ALL_INT_TYPES, 5, 4, 3, 2, 1, 0); - testInt(SIGNED_TYPES, 5, 4, 3, 2, 1, 0, -1); - testInt(SIGNED_TYPES, -1); - testInt(ALL_INT_TYPES, new int[] { }); - - for (int i=0; i<5; i++) { - int len = 50 + random.nextInt(800); - int[] arr = IntStream.generate(() -> random.nextInt(10000) - 5000) - .distinct() - .limit(len) - .toArray(); - testInt(SIGNED_NON_BYTE_TYPES, arr); - - arr = IntStream.generate(() -> random.nextInt(10000)) - .distinct() - .limit(len) - .toArray(); - testInt(CHAR_TYPES, arr); - - arr = IntStream.generate(() -> random.nextInt(127) - 64) - .distinct() - .limit(120) - .toArray(); - testInt(BYTE_TYPES, arr); - } - } - - public void testLong() throws Throwable { - testLong(1L, Long.MIN_VALUE, Long.MAX_VALUE); - testLong(8L, 2L, 5L, 4L, 3L, 9L, 1L); - testLong(new long[] { }); - - // @@@ Random tests - // @@@ More tests for weird values - } - - public void testFloat() throws Throwable { - testFloat(0.0f, -0.0f, -1.0f, 1.0f, 3.14f, Float.MIN_VALUE, Float.MAX_VALUE, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY); - testFloat(new float[] { }); - testFloat(0.0f, 1.0f, 3.14f, Float.NaN); - - // @@@ Random tests - // @@@ More tests for weird values - } - - public void testDouble() throws Throwable { - testDouble(0.0, -0.0, -1.0, 1.0, 3.14, Double.MIN_VALUE, Double.MAX_VALUE, - Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); - testDouble(new double[] { }); - testDouble(0.0f, 1.0f, 3.14f, Double.NaN); - - // @@@ Random tests - // @@@ More tests for weird values - } - - public void testString() throws Throwable { - testString("a", "b", "c"); - testString("c", "b", "a"); - testString("cow", "pig", "horse", "orangutan", "elephant", "dog", "frog", "ant"); - testString("a", "b", "c", "A", "B", "C"); - testString("C", "B", "A", "c", "b", "a"); - - // Tests with hash collisions; Ba/CB, Ca/DB - testString("Ba", "CB"); - testString("Ba", "CB", "Ca", "DB"); - - // Test with null - try { - testString("a", null, "c"); - fail("expected failure"); - } - catch (IllegalArgumentException t) { - // success - } - } - - enum E1 { A, B } - enum E2 { C, D, E, F, G, H } - - public void testEnum() throws Throwable { - testEnum(E1.class); - testEnum(E1.class, "A"); - testEnum(E1.class, "A", "B"); - testEnum(E1.class, "B", "A"); - testEnum(E2.class, "C"); - testEnum(E2.class, "C", "D", "E", "F", "H"); - testEnum(E2.class, "H", "C", "G", "D", "F", "E"); - - // Bad enum class - try { - testEnum((Class) String.class, "A"); - fail("expected failure"); - } - catch (IllegalArgumentException t) { - // success - } - - // Bad enum constants - try { - testEnum(E1.class, "B", "A", "FILE_NOT_FOUND"); - fail("expected failure"); - } - catch (IllegalArgumentException t) { - // success - } - - // Null enum constant - try { - testEnum(E1.class, "A", null, "B"); - fail("expected failure"); - } - catch (IllegalArgumentException t) { - // success - } - } - - private void testType(Object target, int result, Class... labels) throws Throwable { - MethodHandle indy = ((CallSite) BSM_TYPE_SWITCH.invoke(MethodHandles.lookup(), "", switchType(Object.class), labels)).dynamicInvoker(); - assertEquals((int) indy.invoke(target), result); - assertEquals(-1, (int) indy.invoke(null)); - } - - public void testTypes() throws Throwable { - testType("", 0, String.class, Object.class); - testType("", 0, Object.class); - testType("", 1, Integer.class); - testType("", 1, Integer.class, Serializable.class); - testType(E1.A, 0, E1.class, Object.class); - testType(E2.C, 1, E1.class, Object.class); - testType(new Serializable() { }, 1, Comparable.class, Serializable.class); - - // test failures: duplicates, nulls, dominance inversion - } -} diff --git a/test/jdk/java/lang/lang-runtime/boottest/TEST.properties b/test/jdk/java/lang/lang-runtime/boottest/TEST.properties deleted file mode 100755 index 4d7d0f90d06..00000000000 --- a/test/jdk/java/lang/lang-runtime/boottest/TEST.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file identifies root(s) of the test-ng hierarchy. - -TestNG.dirs = . diff --git a/test/jdk/java/lang/lang-runtime/boottest/java.base/java/lang/runtime/CarrierTest.java b/test/jdk/java/lang/lang-runtime/boottest/java.base/java/lang/runtime/CarrierTest.java deleted file mode 100755 index 5d50e23acef..00000000000 --- a/test/jdk/java/lang/lang-runtime/boottest/java.base/java/lang/runtime/CarrierTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang.runtime; - -import java.lang.invoke.MethodType; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; - -/** - * @test - * @key randomness - * @run testng CarrierTest - * @summary unit tests for java.lang.runtime.ExtractorCarriers - */ -@Test -public class CarrierTest { - static final int N_ITER = 1000; - static final Class<?>[] TYPES = { byte.class, short.class, char.class, int.class, long.class, float.class, double.class, boolean.class, Object.class }; - - static Object[] byteVals = { Byte.MIN_VALUE, Byte.MAX_VALUE, (byte) -1, (byte) 0, (byte) 1, (byte) 42 }; - static Object[] shortVals = { Short.MIN_VALUE, Short.MAX_VALUE, (short) -1, (short) 0, (short) 1, (short) 42 }; - static Object[] charVals = { Character.MIN_VALUE, Character.MAX_VALUE, (char) 0, 'a', 'Z' }; - static Object[] intVals = { Integer.MIN_VALUE, Integer.MAX_VALUE, -1, 0, 1, 42 }; - static Object[] longVals = { Long.MIN_VALUE, Long.MAX_VALUE, -1L, 0L, 1L, 42L }; - static Object[] floatVals = { Float.MIN_VALUE, Float.MAX_VALUE, -1.0f, 0.0f, 1.0f, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.NaN }; - static Object[] doubleVals = { Double.MIN_VALUE, Double.MAX_VALUE, -1.0d, 0.0d, 1.0d, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN }; - static Object[] booleanVals = { true, false }; - static Object[] objectVals = {null, "", "Foo", "foo", List.of(), Collections.EMPTY_SET }; - - // @@@ Should use RandomFactory, but can't get that to link - private static final Random random = new Random(System.nanoTime()); - - static Map<Class<?>, Object[]> primVals = Map.of(byte.class, byteVals, - short.class, shortVals, - char.class, charVals, - int.class, intVals, - long.class, longVals, - float.class, floatVals, - double.class, doubleVals, - boolean.class, booleanVals); - - void testCarrier(MethodType type, Object[] values) throws Throwable { - for (PatternCarriers.CarrierFactory cf : PatternCarriers.CarrierFactories.values()) { - assertEquals(type.parameterCount(), values.length); - Object carrier = cf.constructor(type).invokeWithArguments(values); - for (int i = 0; i < values.length; i++) - assertEquals(values[i], cf.component(type, i).invoke(carrier)); - } - } - - void testCarrier(MethodType type) throws Throwable { - // generate data, in a loop - for (int i=0; i<N_ITER; i++) { - Object[] values = new Object[type.parameterCount()]; - for (int j=0; j<type.parameterCount(); j++) { - Class<?> c = type.parameterType(j); - Object[] vals = c.isPrimitive() ? primVals.get(c) : objectVals; - values[j] = vals[random.nextInt(vals.length)]; - } - testCarrier(type, values); - } - } - - public void testCarrier() throws Throwable { - Class[] lotsOfInts = new Class[252]; - Arrays.fill(lotsOfInts, int.class); - - // known types - for (MethodType mt : List.of( - MethodType.methodType(Object.class), - MethodType.methodType(Object.class, int.class), - MethodType.methodType(Object.class, int.class, int.class), - MethodType.methodType(Object.class, Object.class), - MethodType.methodType(Object.class, Object.class, Object.class), - MethodType.methodType(Object.class, byte.class, short.class, char.class, int.class, long.class, float.class, double.class, boolean.class), - MethodType.methodType(Object.class, lotsOfInts))) { - testCarrier(mt); - } - - // random types - for (int i=0; i<N_ITER; i++) { - int nTypes = random.nextInt(10); - Class[] paramTypes = new Class[nTypes]; - Arrays.setAll(paramTypes, ix -> TYPES[random.nextInt(TYPES.length)]); - testCarrier(MethodType.methodType(Object.class, paramTypes)); - } - } -} diff --git a/test/jdk/java/security/SignedObject/Chain.java b/test/jdk/java/security/SignedObject/Chain.java index 71fd79dd4c3..b4a5ea794e6 100644 --- a/test/jdk/java/security/SignedObject/Chain.java +++ b/test/jdk/java/security/SignedObject/Chain.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +/* + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,13 @@ static enum SigAlg { SHA1withDSA("SHA1withDSA"), SHA224withDSA("SHA224withDSA"), SHA256withDSA("SHA256withDSA"), + SHA384withDSA("SHA384withDSA"), + SHA512withDSA("SHA512withDSA"), + + SHA3_224withDSA("SHA3-224withDSA"), + SHA3_256withDSA("SHA3-256withDSA"), + SHA3_384withDSA("SHA3-384withDSA"), + SHA3_512withDSA("SHA3-512withDSA"), SHA1withRSA("Sha1withrSA"), SHA224withRSA("SHA224withRSA"), @@ -79,12 +86,20 @@ static enum SigAlg { SHA512withRSA("SHA512withRSA"), SHA512_224withRSA("SHA512/224withRSA"), SHA512_256withRSA("SHA512/256withRSA"), + SHA3_224withRSA("SHA3-224withRSA"), + SHA3_256withRSA("SHA3-256withRSA"), + SHA3_384withRSA("SHA3-384withRSA"), + SHA3_512withRSA("SHA3-512withRSA"), SHA1withECDSA("SHA1withECDSA"), - SHA256withECDSA("SHA256withECDSA"), SHA224withECDSA("SHA224withECDSA"), + SHA256withECDSA("SHA256withECDSA"), SHA384withECDSA("SHA384withECDSA"), SHA512withECDSA("SHA512withECDSA"), + SHA3_224withECDSA("SHA3-224withECDSA"), + SHA3_256withECDSA("SHA3-256withECDSA"), + SHA3_384withECDSA("SHA3-384withECDSA"), + SHA3_512withECDSA("SHA3-512withECDSA"), MD5andSHA1withRSA("MD5andSHA1withRSA"), @@ -147,7 +162,10 @@ public String toString() { new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default, 1024), new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default), new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default), - new Test(SigAlg.SHA1withRSA, KeyAlg.RSA, Provider.Default), + new Test(SigAlg.SHA3_224withRSA, KeyAlg.RSA, Provider.Default), + new Test(SigAlg.SHA3_256withRSA, KeyAlg.RSA, Provider.Default), + new Test(SigAlg.SHA3_384withRSA, KeyAlg.RSA, Provider.Default), + new Test(SigAlg.SHA3_512withRSA, KeyAlg.RSA, Provider.Default), new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Sun, 1024), new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.Sun, 2048), new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.Sun, 2048), diff --git a/test/jdk/java/util/StringJoiner/MergeTest.java b/test/jdk/java/util/StringJoiner/MergeTest.java index 181a25d4447..a2511961016 100644 --- a/test/jdk/java/util/StringJoiner/MergeTest.java +++ b/test/jdk/java/util/StringJoiner/MergeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @summary test StringJoiner::merge * @modules java.base/jdk.internal.util * @requires os.maxMemory > 4G - * @run testng/othervm -Xmx4g MergeTest + * @run testng/othervm -Xmx4g -XX:+CompactStrings MergeTest */ import java.util.StringJoiner; diff --git a/test/jdk/java/util/StringJoiner/StringJoinerTest.java b/test/jdk/java/util/StringJoiner/StringJoinerTest.java index 918823d23e9..f40179f3057 100644 --- a/test/jdk/java/util/StringJoiner/StringJoinerTest.java +++ b/test/jdk/java/util/StringJoiner/StringJoinerTest.java @@ -26,7 +26,7 @@ * @summary tests StringJoinerTest * @modules java.base/jdk.internal.util * @requires os.maxMemory > 4G - * @run testng/othervm -Xmx4g StringJoinerTest + * @run testng/othervm -Xmx4g -XX:+CompactStrings StringJoinerTest * @author Jim Gish */ import java.util.ArrayList; diff --git a/test/jdk/java/util/zip/GZIP/GZIPOutputStreamHeaderTest.java b/test/jdk/java/util/zip/GZIP/GZIPOutputStreamHeaderTest.java new file mode 100644 index 00000000000..93c2e91fea8 --- /dev/null +++ b/test/jdk/java/util/zip/GZIP/GZIPOutputStreamHeaderTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +/** + * @test + * @bug 8244706 + * @summary Verify that the OS header flag in the stream written out by java.util.zip.GZIPOutputStream + * has the correct expected value + * @run testng GZIPOutputStreamHeaderTest + */ +public class GZIPOutputStreamHeaderTest { + + private static final int OS_HEADER_INDEX = 9; + private static final int HEADER_VALUE_OS_UNKNOWN = 255; + + /** + * Test that the {@code OS} header field in the GZIP output stream + * has a value of {@code 255} which represents "unknown" + */ + @Test + public void testOSHeader() throws Exception { + final String data = "Hello world!!!"; + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (final GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos);) { + gzipOutputStream.write(data.getBytes(StandardCharsets.UTF_8)); + } + final byte[] compressed = baos.toByteArray(); + Assert.assertNotNull(compressed, "Compressed data is null"); + Assert.assertEquals(toUnsignedByte(compressed[OS_HEADER_INDEX]), HEADER_VALUE_OS_UNKNOWN, + "Unexpected value for OS header"); + // finally verify that the compressed data is readable back to the original + final String uncompressed; + try (final ByteArrayOutputStream os = new ByteArrayOutputStream(); + final ByteArrayInputStream bis = new ByteArrayInputStream(compressed); + final GZIPInputStream gzipInputStream = new GZIPInputStream(bis)) { + gzipInputStream.transferTo(os); + uncompressed = new String(os.toByteArray(), StandardCharsets.UTF_8); + } + Assert.assertEquals(uncompressed, data, "Unexpected data read from GZIPInputStream"); + } + + private static int toUnsignedByte(final byte b) { + return b & 0xff; + } +} diff --git a/test/jdk/javax/swing/Box/TestBoxFiller.java b/test/jdk/javax/swing/Box/TestBoxFiller.java new file mode 100644 index 00000000000..e1dd269be0c --- /dev/null +++ b/test/jdk/javax/swing/Box/TestBoxFiller.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8253016 + @key headful + @summary Verifies Box.Filler components should be unfocusable by default + @run main TestBoxFiller + */ +import java.awt.ContainerOrderFocusTraversalPolicy; +import java.awt.KeyboardFocusManager; +import java.beans.PropertyChangeEvent; +import javax.swing.Box; +import javax.swing.JFrame; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import java.awt.Robot; +import java.awt.event.KeyEvent; + +public class TestBoxFiller +{ + private static JFrame frame; + private static void showFocusOwner(PropertyChangeEvent e) + { + Object c = e.getNewValue(); + if (c instanceof Box.Filler) { + throw new RuntimeException("Box.Filler having focus"); + } + } + + public static void main(String[] args) throws Exception + { + try { + Robot robot = new Robot(); + robot.setAutoDelay(100); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + KeyboardFocusManager m = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + m.addPropertyChangeListener("focusOwner", TestBoxFiller::showFocusOwner); + + Box box = Box.createHorizontalBox(); + JTextField tf1 = new JTextField("Test"); + tf1.setColumns(40); + JTextField tf2 = new JTextField("Test"); + tf2.setColumns(40); + box.add(tf1); + box.add(Box.createHorizontalStrut(20)); + box.add(tf2); + frame.setContentPane(box); + frame.setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy()); + frame.pack(); + frame.setVisible(true); + frame.setLocationRelativeTo(null); + tf1.requestFocusInWindow(); + }); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + } finally { + if (frame != null) { + SwingUtilities.invokeAndWait(frame::dispose); + } + } + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/7154841/bug7154841.java b/test/jdk/javax/swing/JPopupMenu/7154841/bug7154841.java index 69508b93a3c..b7a7494c992 100644 --- a/test/jdk/javax/swing/JPopupMenu/7154841/bug7154841.java +++ b/test/jdk/javax/swing/JPopupMenu/7154841/bug7154841.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ public class bug7154841 { private static void initAndShowUI() { popupMenu = new JPopupMenu(); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 400; i++) { JRadioButtonMenuItem item = new JRadioButtonMenuItem(" Test " + i); item.addMouseMotionListener(new MouseMotionAdapter() { @Override diff --git a/test/jdk/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java b/test/jdk/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java index 7835c3c4da4..78160283a4a 100644 --- a/test/jdk/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java +++ b/test/jdk/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,11 +104,11 @@ public Object getElementAt(int index) { @Override public int getSize() { - return 100; + return 400; } }); - combobox.setMaximumRowCount(100); + combobox.setMaximumRowCount(400); combobox.putClientProperty("JComboBox.isPopDown", true); frame.getContentPane().add(combobox); frame.setVisible(true); diff --git a/test/jdk/jdk/jfr/tool/TestDisassemble.java b/test/jdk/jdk/jfr/tool/TestDisassemble.java index 29d28531a02..94d2d7b4346 100644 --- a/test/jdk/jdk/jfr/tool/TestDisassemble.java +++ b/test/jdk/jdk/jfr/tool/TestDisassemble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ /** * @test + * @bug 8253050 * @summary Test jfr split * @key jfr * @requires vm.hasJFR @@ -55,13 +56,16 @@ public static void main(String[] args) throws Throwable { Path recordingFileA = Paths.get("many-chunks-A-" + dateText + ".jfr"); Path recordingFileB = Paths.get("many-chunks-B-" + dateText + ".jfr"); Path recordingFileC = Paths.get("many-chunks-C-" + dateText + ".jfr"); + Path recordingFileD = Paths.get("many-chunks-D-" + dateText + ".jfr"); makeRecordingWithChunks(6, recordingFileA); Files.copy(recordingFileA, recordingFileB); Files.copy(recordingFileA, recordingFileC); + Files.copy(recordingFileA, recordingFileD); String fileAText = recordingFileA.toAbsolutePath().toString(); String fileBText = recordingFileB.toAbsolutePath().toString(); String fileCText = recordingFileC.toAbsolutePath().toString(); + String fileDText = recordingFileD.toAbsolutePath().toString(); OutputAnalyzer output = ExecuteHelper.jfr("disassemble"); output.shouldContain("missing file"); @@ -97,6 +101,15 @@ public static void main(String[] args) throws Throwable { // sanity check output = ExecuteHelper.jfr("disassemble", "--max-size", "10000", fileCText); verifyRecording(fileCText.substring(0, fileCText.length() - 4) + "_01.jfr"); + + // test JDK-8253050 + output = ExecuteHelper.jfr("disassemble", "--max-chunks", "1", fileDText); + String chunks = output.firstMatch("File consists of (\\d+) chunks", 1); + output.shouldContain("The recording will be split into " + chunks + " files"); + String chunkFilePrefix = fileDText.substring(0, fileDText.length() - 4) + "_"; + for (long i = 0; i < Long.parseLong(chunks); i++) { + verifyRecording(chunkFilePrefix + String.format("%0" + chunks.length() + "d", i) + ".jfr"); + } } private static void verifyRecording(String name) throws IOException { diff --git a/test/jdk/sun/security/ec/SignatureKAT.java b/test/jdk/sun/security/ec/SignatureKAT.java new file mode 100644 index 00000000000..d1fa6f702cf --- /dev/null +++ b/test/jdk/sun/security/ec/SignatureKAT.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Convert; + +import java.security.*; +import java.security.spec.*; +import java.math.*; +import java.util.*; + +/* + * @test + * @bug 8172366 + * @summary Known Answer Test for ECDSA signature + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main/othervm SignatureKAT + */ +public class SignatureKAT { + + private static String checkHex(String hex) { + // if hex length is odd, need to prepend 0 + if (hex.length() % 2 != 0) { + hex = "0" + hex; + } + return hex; + } + + private static class CurveData { + private String name; + private byte[] msgBytes; + private BigInteger priv; + private BigInteger pubX; + private BigInteger pubY; + + private static BigInteger toBigInteger(String hex) { + byte[] bytes = Convert.hexStringToByteArray(checkHex(hex)); + return new BigInteger(1, bytes); + } + CurveData(String name, String msg, String priv, String pubX, + String pubY) { + this.name = name; + this.msgBytes = msg.getBytes(); + this.priv = toBigInteger(priv); + this.pubX = toBigInteger(pubX); + this.pubY = toBigInteger(pubY); + } + } + + private static class TestData { + private String sigName; + private CurveData cd; + private byte[] expSig; + + TestData(String sigName, CurveData cd, String r, String s) { + this.sigName = sigName; + this.cd = cd; + if (r.length() != s.length() || r != checkHex(r) || + s != checkHex(s)) { + throw new RuntimeException("Error: invalid r, s"); + } + this.expSig = Convert.hexStringToByteArray(r + s); + } + } + + // These test values are from the examples shown in the page below: + // https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values + private static final CurveData P_256 = new CurveData( + "secp256r1", "Example of ECDSA with P-256", + "C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96", + "B7E08AFDFE94BAD3F1DC8C734798BA1C62B3A0AD1E9EA2A38201CD0889BC7A19", + "3603F747959DBF7A4BB226E41928729063ADC7AE43529E61B563BBC606CC5E09" + ); + + private static final CurveData P_384 = new CurveData( + "secp384r1", "Example of ECDSA with P-384", + "F92C02ED629E4B48C0584B1C6CE3A3E3B4FAAE4AFC6ACB0455E73DFC392E6A0AE393A8565E6B9714D1224B57D83F8A08", + "3BF701BC9E9D36B4D5F1455343F09126F2564390F2B487365071243C61E6471FB9D2AB74657B82F9086489D9EF0F5CB5", + "D1A358EAFBF952E68D533855CCBDAA6FF75B137A5101443199325583552A6295FFE5382D00CFCDA30344A9B5B68DB855" + ); + + private static final CurveData P_521 = new CurveData( + "secp521r1", "Example of ECDSA with P-521", + "100085F47B8E1B8B11B7EB33028C0B2888E304BFC98501955B45BBA1478DC184EEEDF09B86A5F7C21994406072787205E69A63709FE35AA93BA333514B24F961722", + "98E91EEF9A68452822309C52FAB453F5F117C1DA8ED796B255E9AB8F6410CCA16E59DF403A6BDC6CA467A37056B1E54B3005D8AC030DECFEB68DF18B171885D5C4", + "164350C321AECFC1CCA1BA4364C9B15656150B4B78D6A48D7D28E7F31985EF17BE8554376B72900712C4B83AD668327231526E313F5F092999A4632FD50D946BC2E" + ); + + private static TestData[] TEST_DATUM = { + // secp256r1, secp384r1, and secp521r1 remain enabled + new TestData("SHA256withECDSAinP1363Format", P_256, + "2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F", + "DC42C2122D6392CD3E3A993A89502A8198C1886FE69D262C4B329BDB6B63FAF1"), + new TestData("SHA3-256withECDSAinP1363Format", P_256, + "2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F", + "0A861C2526900245C73BACB9ADAEC1A5ACB3BA1F7114A3C334FDCD5B7690DADD"), + new TestData("SHA384withECDSAinP1363Format", P_384, + "30EA514FC0D38D8208756F068113C7CADA9F66A3B40EA3B313D040D9B57DD41A332795D02CC7D507FCEF9FAF01A27088", + "CC808E504BE414F46C9027BCBF78ADF067A43922D6FCAA66C4476875FBB7B94EFD1F7D5DBE620BFB821C46D549683AD8"), + new TestData("SHA3-384withECDSAinP1363Format", P_384, + "30EA514FC0D38D8208756F068113C7CADA9F66A3B40EA3B313D040D9B57DD41A332795D02CC7D507FCEF9FAF01A27088", + "691B9D4969451A98036D53AA725458602125DE74881BBC333012CA4FA55BDE39D1BF16A6AAE3FE4992C567C6E7892337"), + new TestData("SHA512withECDSAinP1363Format", P_521, + "0140C8EDCA57108CE3F7E7A240DDD3AD74D81E2DE62451FC1D558FDC79269ADACD1C2526EEEEF32F8C0432A9D56E2B4A8A732891C37C9B96641A9254CCFE5DC3E2BA", + "00D72F15229D0096376DA6651D9985BFD7C07F8D49583B545DB3EAB20E0A2C1E8615BD9E298455BDEB6B61378E77AF1C54EEE2CE37B2C61F5C9A8232951CB988B5B1"), + new TestData("SHA3-512withECDSAinP1363Format", P_521, + "0140C8EDCA57108CE3F7E7A240DDD3AD74D81E2DE62451FC1D558FDC79269ADACD1C2526EEEEF32F8C0432A9D56E2B4A8A732891C37C9B96641A9254CCFE5DC3E2BA", + "00B25188492D58E808EDEBD7BF440ED20DB771CA7C618595D5398E1B1C0098E300D8C803EC69EC5F46C84FC61967A302D366C627FCFA56F87F241EF921B6E627ADBF"), + }; + + private static void runTest(TestData td) throws Exception { + System.out.println("Testing " + td.sigName + " with " + td.cd.name); + + AlgorithmParameters params = + AlgorithmParameters.getInstance("EC", "SunEC"); + params.init(new ECGenParameterSpec(td.cd.name)); + ECParameterSpec ecParams = + params.getParameterSpec(ECParameterSpec.class); + + KeyFactory kf = KeyFactory.getInstance("EC", "SunEC"); + PrivateKey privKey = kf.generatePrivate + (new ECPrivateKeySpec(td.cd.priv, ecParams)); + + Signature sig = Signature.getInstance(td.sigName, "SunEC"); + sig.initSign(privKey); + sig.update(td.cd.msgBytes); + // NOTE: there is no way to set the nonce value into current SunEC + // ECDSA signature, thus the output signature bytes likely won't + // match the expected signature bytes + byte[] ov = sig.sign(); + + ECPublicKeySpec pubKeySpec = new ECPublicKeySpec + (new ECPoint(td.cd.pubX, td.cd.pubY), ecParams); + PublicKey pubKey = kf.generatePublic(pubKeySpec); + + sig.initVerify(pubKey); + sig.update(td.cd.msgBytes); + if (!sig.verify(ov)) { + throw new RuntimeException("Error verifying actual sig bytes"); + } + + sig.update(td.cd.msgBytes); + if (!sig.verify(td.expSig)) { + throw new RuntimeException("Error verifying expected sig bytes"); + } + } + + public static void main(String[] args) throws Exception { + for (TestData td : TEST_DATUM) { + runTest(td); + } + } +} diff --git a/test/jdk/sun/security/ec/SignatureOffsets.java b/test/jdk/sun/security/ec/SignatureOffsets.java index 3570258c861..3ea886a3f2a 100644 --- a/test/jdk/sun/security/ec/SignatureOffsets.java +++ b/test/jdk/sun/security/ec/SignatureOffsets.java @@ -43,6 +43,10 @@ * @run main SignatureOffsets SunEC SHA224withECDSA * @run main SignatureOffsets SunEC SHA384withECDSA * @run main SignatureOffsets SunEC SHA512withECDSA + * @run main SignatureOffsets SunEC SHA3-256withECDSA + * @run main SignatureOffsets SunEC SHA3-224withECDSA + * @run main SignatureOffsets SunEC SHA3-384withECDSA + * @run main SignatureOffsets SunEC SHA3-512withECDSA */ public class SignatureOffsets { diff --git a/test/jdk/sun/security/ec/SignedObjectChain.java b/test/jdk/sun/security/ec/SignedObjectChain.java index 6a5b7c93f66..cfeff8c1ad5 100644 --- a/test/jdk/sun/security/ec/SignedObjectChain.java +++ b/test/jdk/sun/security/ec/SignedObjectChain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8050374 8146293 + * @bug 8050374 8146293 8172366 * @summary Verify a chain of signed objects * @library /test/lib * @build jdk.test.lib.SigTestUtil @@ -41,10 +41,14 @@ public Test(Chain.SigAlg sigAlg) { private static final Test[] tests = { new Test(Chain.SigAlg.SHA1withECDSA), - new Test(Chain.SigAlg.SHA256withECDSA), new Test(Chain.SigAlg.SHA224withECDSA), + new Test(Chain.SigAlg.SHA256withECDSA), new Test(Chain.SigAlg.SHA384withECDSA), new Test(Chain.SigAlg.SHA512withECDSA), + new Test(Chain.SigAlg.SHA3_224withECDSA), + new Test(Chain.SigAlg.SHA3_256withECDSA), + new Test(Chain.SigAlg.SHA3_384withECDSA), + new Test(Chain.SigAlg.SHA3_512withECDSA), }; public static void main(String argv[]) { diff --git a/test/jdk/sun/security/rsa/SignatureOffsets.java b/test/jdk/sun/security/rsa/SignatureOffsets.java index 1db628cac31..15df99c4665 100644 --- a/test/jdk/sun/security/rsa/SignatureOffsets.java +++ b/test/jdk/sun/security/rsa/SignatureOffsets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ /* * @test - * @bug 8050374 8146293 + * @bug 8050374 8146293 8172366 * @key randomness * @summary This test validates signature verification * Signature.verify(byte[], int, int). The test uses RandomFactory to @@ -46,6 +46,10 @@ * @run main SignatureOffsets SunRsaSign SHA512withRSA * @run main SignatureOffsets SunRsaSign SHA512/224withRSA * @run main SignatureOffsets SunRsaSign SHA512/256withRSA + * @run main SignatureOffsets SunRsaSign SHA3-224withRSA + * @run main SignatureOffsets SunRsaSign SHA3-256withRSA + * @run main SignatureOffsets SunRsaSign SHA3-384withRSA + * @run main SignatureOffsets SunRsaSign SHA3-512withRSA */ public class SignatureOffsets { diff --git a/test/jdk/sun/security/rsa/pss/PSSParametersTest.java b/test/jdk/sun/security/rsa/pss/PSSParametersTest.java index 2fde948fdc9..c71e5bb34a4 100644 --- a/test/jdk/sun/security/rsa/pss/PSSParametersTest.java +++ b/test/jdk/sun/security/rsa/pss/PSSParametersTest.java @@ -31,7 +31,7 @@ /** * @test - * @bug 8146293 8242556 + * @bug 8146293 8242556 8172366 * @summary Test RSASSA-PSS AlgorithmParameters impl of SunRsaSign provider. * @run main PSSParametersTest */ @@ -50,6 +50,8 @@ public static void main(String[] args) throws Exception { System.out.println("Testing against custom parameters"); test(new PSSParameterSpec("SHA-512/224", "MGF1", MGF1ParameterSpec.SHA384, 100, 1)); + test(new PSSParameterSpec("SHA3-256", "MGF1", + new MGF1ParameterSpec("SHA3-256"), 256>>3, 1)); System.out.println("Test Passed"); } @@ -57,6 +59,7 @@ public static void main(String[] args) throws Exception { // bytes, then initialize w/ the DER bytes, retrieve the spec. // compare both spec for equality and throw exception if the check failed. private static void test(PSSParameterSpec spec) throws Exception { + System.out.println("Testing PSS spec: " + spec); String ALGORITHMS[] = { PSS_ALGO, PSS_OID }; for (String alg : ALGORITHMS) { AlgorithmParameters params = AlgorithmParameters.getInstance @@ -67,9 +70,9 @@ private static void test(PSSParameterSpec spec) throws Exception { (alg, PROVIDER); params2.init(encoded); PSSParameterSpec spec2 = params2.getParameterSpec - (PSSParameterSpec.class); + (PSSParameterSpec.class); if (!isEqual(spec, spec2)) { - throw new RuntimeException("Spec check Failed for " + alg); + throw new RuntimeException("Spec check Failed for " + alg); } } } diff --git a/test/jdk/sun/security/rsa/pss/SignatureTest2.java b/test/jdk/sun/security/rsa/pss/SignatureTest2.java index f5104842001..ea548d04dad 100644 --- a/test/jdk/sun/security/rsa/pss/SignatureTest2.java +++ b/test/jdk/sun/security/rsa/pss/SignatureTest2.java @@ -31,7 +31,7 @@ /** * @test - * @bug 8146293 8238448 + * @bug 8146293 8238448 8172366 * @summary Create a signature for RSASSA-PSS and get its signed data. * re-initiate the signature with the public key. The signature * can be verified by acquired signed data. @@ -68,7 +68,8 @@ public class SignatureTest2 { */ private static final String[] DIGEST_ALG = { "SHA-1", "SHA-224", "SHA-256", "SHA-384", - "SHA-512", "SHA-512/224", "SHA-512/256" + "SHA-512", "SHA-512/224", "SHA-512/256", + "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512" }; private static final String SIG_ALG = "RSASSA-PSS"; diff --git a/test/jdk/sun/security/rsa/pss/TestPSSKeySupport.java b/test/jdk/sun/security/rsa/pss/TestPSSKeySupport.java index c9c7a27e186..7db7774870c 100644 --- a/test/jdk/sun/security/rsa/pss/TestPSSKeySupport.java +++ b/test/jdk/sun/security/rsa/pss/TestPSSKeySupport.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8146293 8242556 + * @bug 8146293 8242556 8172366 * @summary Test RSASSA-PSS Key related support such as KeyPairGenerator * and KeyFactory of the SunRsaSign provider */ @@ -145,11 +145,18 @@ public static void main(String[] args) throws Exception { KeyPair kp2 = kpg.generateKeyPair(); checkKeyPair(kp2); + params = new PSSParameterSpec("SHA3-256", "MGF1", + new MGF1ParameterSpec("SHA3-256"), 32, 1); + kpg.initialize(new RSAKeyGenParameterSpec(2048, pubExp, params)); + KeyPair kp3 = kpg.generateKeyPair(); + checkKeyPair(kp3); + KeyFactory kf = KeyFactory.getInstance(ALGO, "SunRsaSign"); test(kf, kp.getPublic()); test(kf, kp.getPrivate()); test(kf, kp2.getPublic()); test(kf, kp2.getPrivate()); - + test(kf, kp3.getPublic()); + test(kf, kp3.getPrivate()); } } diff --git a/test/langtools/jdk/jshell/CompletionSuggestionTest.java b/test/langtools/jdk/jshell/CompletionSuggestionTest.java index b78b25e33df..1a024e29887 100644 --- a/test/langtools/jdk/jshell/CompletionSuggestionTest.java +++ b/test/langtools/jdk/jshell/CompletionSuggestionTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8131025 8141092 8153761 8145263 8131019 8175886 8176184 8176241 8176110 8177466 8197439 8221759 8234896 + * @bug 8131025 8141092 8153761 8145263 8131019 8175886 8176184 8176241 8176110 8177466 8197439 8221759 8234896 8240658 * @summary Test Completion and Documentation * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -698,6 +698,27 @@ public void testMemberReferences() { assertCompletion("FI2<Object, String> fi = C::|", true, "statConvert1", "statConvert3"); } + public void testBrokenLambdaCompletion() { + assertEval("interface Consumer<T> { public void consume(T t); }"); + assertEval("interface Function<T, R> { public R convert(T t); }"); + assertEval("<T> void m1(T t, Consumer<T> f) { }"); + assertCompletion("m1(\"\", x -> {x.tri|", "trim()"); + assertEval("<T> void m2(T t, Function<T, String> f) { }"); + assertCompletion("m2(\"\", x -> {x.tri|", "trim()"); + assertEval("<T> void m3(T t, Consumer<T> f, int i) { }"); + assertCompletion("m3(\"\", x -> {x.tri|", "trim()"); + assertEval("<T> void m4(T t, Function<T, String> f, int i) { }"); + assertCompletion("m4(\"\", x -> {x.tri|", "trim()"); + assertEval("<T> T m5(Consumer<T> f) { return null; }"); + assertCompletion("String s = m5(x -> {x.tri|", "trim()"); + assertEval("<T> T m6(Function<T, String> f) { return null; }"); + assertCompletion("String s = m6(x -> {x.tri|", "trim()"); + assertEval("<T> T m7(Consumer<T> f, int i) { return null; }"); + assertCompletion("String s = m7(x -> {x.tri|", "trim()"); + assertEval("<T> T m8(Function<T, String> f, int i) { return null; }"); + assertCompletion("String s = m8(x -> {x.tri|", "trim()"); + } + @BeforeMethod public void setUp() { super.setUp(); diff --git a/test/langtools/tools/doclint/CoverageExtras.java b/test/langtools/tools/doclint/CoverageExtras.java index 5db3edf1a0e..67288cfa41c 100644 --- a/test/langtools/tools/doclint/CoverageExtras.java +++ b/test/langtools/tools/doclint/CoverageExtras.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * 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,7 +21,7 @@ * questions. */ -/** +/* * @test * @bug 8006263 * @summary Supplementary test cases needed for doclint @@ -29,7 +29,6 @@ */ import com.sun.tools.doclint.Checker; -import com.sun.tools.doclint.Entity; import com.sun.tools.doclint.HtmlTag; import com.sun.tools.doclint.Messages; import java.util.Objects; diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java index 74be213312f..ce453a2779c 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java @@ -46,10 +46,11 @@ public class Patterns { private ToolBox tb = new ToolBox(); public static void main(String[] args) throws Exception { - new Patterns().run(); + new Patterns().runBinding(); + new Patterns().runDeconstruction(); } - public void run() throws Exception { + public void runBinding() throws Exception { String out = new JavapTask(tb) .options("-private", "-verbose") @@ -162,6 +163,112 @@ public void run() throws Exception { } } + public void runDeconstruction() throws Exception { + String out = new JavapTask(tb) + .options("-private", + "-verbose") + .classpath(System.getProperty("test.classes")) + .classes("Patterns$DeconstructionPattern") + .run() + .getOutputLines(Task.OutputKind.DIRECT) + .stream() + .collect(Collectors.joining("\n")); + + String constantPool = out.substring(0, out.indexOf('{')); + + out = out.replaceAll("(?ms) *Code:.*?\n( *RuntimeInvisibleTypeAnnotations:)", "$1"); + out = out.substring(out.indexOf('{')); + out = out.substring(0, out.lastIndexOf('}') + 1); + + String A = snipCPNumber(constantPool, "LPatterns$DeconstructionPattern$A;"); + String CA = snipCPNumber(constantPool, "LPatterns$DeconstructionPattern$CA;"); + String value = snipCPNumber(constantPool, "value"); + + String expected = """ + { + private static final java.lang.Object o; + descriptor: Ljava/lang/Object; + flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL + + private static final boolean B1s; + descriptor: Z + flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL + + private static final boolean B1m; + descriptor: Z + flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL + + private final boolean B2s; + descriptor: Z + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + + private final boolean B2m; + descriptor: Z + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + + public Patterns$DeconstructionPattern(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleTypeAnnotations: + 0: #_A_(): LOCAL_VARIABLE, {start_pc=284, length=11, index=2} + Patterns$DeconstructionPattern$A + 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=328, length=11, index=3} + Patterns$DeconstructionPattern$CA( + value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] + ) + 2: #_A_(): LOCAL_VARIABLE, {start_pc=30, length=11, index=1} + Patterns$DeconstructionPattern$A + 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=71, length=11, index=1} + Patterns$DeconstructionPattern$CA( + value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] + ) + 4: #_A_(): LOCAL_VARIABLE, {start_pc=114, length=11, index=2} + Patterns$DeconstructionPattern$A + 5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=158, length=11, index=3} + Patterns$DeconstructionPattern$CA( + value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] + ) + 6: #_A_(): LOCAL_VARIABLE, {start_pc=199, length=11, index=2} + Patterns$DeconstructionPattern$A + 7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=243, length=11, index=3} + Patterns$DeconstructionPattern$CA( + value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] + ) + + void testPatterns(); + descriptor: ()V + flags: (0x0000) + RuntimeInvisibleTypeAnnotations: + 0: #_A_(): LOCAL_VARIABLE, {start_pc=28, length=11, index=2} + Patterns$DeconstructionPattern$A + 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=72, length=11, index=3} + Patterns$DeconstructionPattern$CA( + value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] + ) + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + RuntimeInvisibleTypeAnnotations: + 0: #_A_(): LOCAL_VARIABLE, {start_pc=30, length=11, index=0} + Patterns$DeconstructionPattern$A + 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=70, length=11, index=0} + Patterns$DeconstructionPattern$CA( + value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] + ) + 2: #_A_(): LOCAL_VARIABLE, {start_pc=110, length=11, index=1} + Patterns$DeconstructionPattern$A + 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=151, length=11, index=2} + Patterns$DeconstructionPattern$CA( + value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] + ) + }""".replace("_A_", A).replace("_CA_", CA).replace("_value_", value); + + if (!expected.equals(out)) { + throw new AssertionError("Unexpected output:\n" + out + "\nexpected:\n" + expected); + } + } + private String snipCPNumber(String constantPool, String expectedConstant) { Matcher m = Pattern.compile("#([0-9]+).*" + Pattern.quote(expectedConstant)) .matcher(constantPool); @@ -219,4 +326,47 @@ void testPatternsDesugared() { boolean B8sx = o instanceof String && (s = (String) o) == s && s.isEmpty(); } } + + static class DeconstructionPattern { + @Target(ElementType.TYPE_USE) + @Repeatable(CA.class) + @interface A {} + @Target(ElementType.TYPE_USE) + @interface CA { + public A[] value(); + } + + private static final Object o = ""; + private static final boolean B1s = o instanceof R(@A String s) && s.isEmpty(); + private static final boolean B1m = o instanceof R(@A @A String s) && s.isEmpty(); + private final boolean B2s = o instanceof R(@A String s) && s.isEmpty(); + private final boolean B2m = o instanceof R(@A @A String s) && s.isEmpty(); + + static { + boolean B3s = o instanceof R(@A String s) && s.isEmpty(); + boolean B3m = o instanceof R(@A @A String s) && s.isEmpty(); + } + + { + boolean B4s = o instanceof R(@A String s) && s.isEmpty(); + boolean B4m = o instanceof R(@A @A String s) && s.isEmpty(); + } + + { + boolean B5s = o instanceof R(@A String s) && s.isEmpty(); + boolean B5m = o instanceof R(@A @A String s) && s.isEmpty(); + } + + public DeconstructionPattern() { + boolean B6s = o instanceof R(@A String s) && s.isEmpty(); + boolean B6m = o instanceof R(@A @A String s) && s.isEmpty(); + } + + void testPatterns() { + boolean B7s = o instanceof R(@A String s) && s.isEmpty(); + boolean B7m = o instanceof R(@A @A String s) && s.isEmpty(); + } + + record R(String s) {} + } } diff --git a/test/langtools/tools/javac/api/TestGetScopeResult.java b/test/langtools/tools/javac/api/TestGetScopeResult.java index 8f32df197d9..b2a2e500e03 100644 --- a/test/langtools/tools/javac/api/TestGetScopeResult.java +++ b/test/langtools/tools/javac/api/TestGetScopeResult.java @@ -23,12 +23,13 @@ /* * @test - * @bug 8205418 8207229 8207230 8230847 8245786 8247334 8248641 + * @bug 8205418 8207229 8207230 8230847 8245786 8247334 8248641 8240658 * @summary Test the outcomes from Trees.getScope * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.comp * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util + * @compile TestGetScopeResult.java */ import java.io.IOException; @@ -62,6 +63,7 @@ import com.sun.source.util.TreePathScanner; import com.sun.source.util.Trees; import com.sun.tools.javac.api.JavacScope; +import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.comp.Analyzer; @@ -192,6 +194,19 @@ static interface BiFunction<R, P, Q> { } }""", invocationInMethodInvocation); + + String[] infer = { + "c:java.lang.String", + "super:java.lang.Object", + "this:Test" + }; + + doTest("class Test { void test() { cand(\"\", c -> { }); } <T>void cand(T t, I<T> i) { } interface I<T> { public String test(T s); } }", + infer); + doTest("class Test { void test() { cand(\"\", c -> { }); } <T>void cand(T t, I<T> i, int j) { } interface I<T> { public void test(T s); } }", + infer); + doTest("class Test { void test() { cand(\"\", c -> { }); } <T>void cand(T t, I<T> i, int j) { } interface I<T> { public String test(T s); } }", + infer); } public void doTest(String code, String... expected) throws IOException { @@ -208,24 +223,29 @@ public String getCharContent(boolean ignoreEncodingErrors) { } JavacTask t = (JavacTask) c.getTask(null, fm, null, null, null, List.of(new MyFileObject())); CompilationUnitTree cut = t.parse().iterator().next(); - t.analyze(); - List<String> actual = new ArrayList<>(); + ((JavacTaskImpl)t).enter(); - new TreePathScanner<Void, Void>() { - @Override - public Void visitLambdaExpression(LambdaExpressionTree node, Void p) { - Scope scope = Trees.instance(t).getScope(new TreePath(getCurrentPath(), node.getBody())); - actual.addAll(dumpScope(scope)); - return super.visitLambdaExpression(node, p); - } - }.scan(cut, null); + for (int r = 0; r < 2; r++) { + List<String> actual = new ArrayList<>(); - List<String> expectedList = List.of(expected); + new TreePathScanner<Void, Void>() { + @Override + public Void visitLambdaExpression(LambdaExpressionTree node, Void p) { + Scope scope = Trees.instance(t).getScope(new TreePath(getCurrentPath(), node.getBody())); + actual.addAll(dumpScope(scope)); + return super.visitLambdaExpression(node, p); + } + }.scan(cut, null); + + List<String> expectedList = List.of(expected); - if (!expectedList.equals(actual)) { - throw new IllegalStateException("Unexpected scope content: " + actual + "\n" + - "expected: " + expectedList); + if (!expectedList.equals(actual)) { + throw new IllegalStateException("Unexpected scope content: " + actual + "\n" + + "expected: " + expectedList); + } + + t.analyze(); } } } diff --git a/test/langtools/tools/javac/api/lambdaErrorRecovery/TestGetTypeMirrorReference.java b/test/langtools/tools/javac/api/lambdaErrorRecovery/TestGetTypeMirrorReference.java new file mode 100644 index 00000000000..741835a0a4f --- /dev/null +++ b/test/langtools/tools/javac/api/lambdaErrorRecovery/TestGetTypeMirrorReference.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8240658 + * @summary Verify that broken method invocations with lambdas get type inference done + * @modules jdk.compiler + * @compile --enable-preview -source ${jdk.version} TestGetTypeMirrorReference.java + * @run main/othervm --enable-preview TestGetTypeMirrorReference + */ + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.Tree; +import com.sun.source.util.*; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import javax.lang.model.type.TypeMirror; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +/* + * This test verifies proper error recovery for method invocations which need + * type inference, and have lambdas as arguments. + * + * The test will read the adjacent TestGetTypeMirrorReferenceData.java, parse and + * attribute it, and call Trees.getTypeMirror on each place marked, in a block + * comment, with: + * getTypeMirror:<expected-typemirror-kind>:<expected-typemirror-toString> + * The actual retrieved TypeMirror will be checked against the provided description, + * verifying the return value of TypeMirror.getKind and TypeMirror.toString(). + * + * The AST for TestGetTypeMirrorReferenceData.java will also be printed using + * Tree.toString(), and compared to the expected AST form. + */ +public class TestGetTypeMirrorReference { + + private static final String JDK_VERSION = + Integer.toString(Runtime.version().feature()); + + public static void main(String... args) throws IOException { + analyze("TestGetTypeMirrorReferenceData.java", + """ + package test; + + public class TestGetTypeMirrorReferenceData { + + public TestGetTypeMirrorReferenceData() { + super(); + } + + private static void test() { + Test.of(1).convert((c1)->{ + Object o = c1; + }); + Test.of(1).consume((c2)->{ + Object o = c2; + return null; + }); + Test.of(1).consumeWithParam((c3)->{ + Object o = c3; + }); + convert(0, (c4)->{ + Object o = c4; + }); + consume(0, (c5)->{ + Object o = c5; + }); + convertVarArgs(0, (c6)->{ + Object o = c6; + }, 1, 2, 3, 4); + consumeVarArgs(0, (c7)->{ + Object o = c7; + }, 1, 2, 3, 4); + convertVarArgs2(0, (c8)->{ + Object o = c8; + }, (c8)->{ + Object o = c8; + }); + consumeVarArgs2(0, (c9)->{ + Object o = c9; + }, (c9)->{ + Object o = c9; + }); + } + + public <T, R>R convert(T t, Function<T, R> f, int i) { + return null; + } + + public <T>void consume(T t, Consumer<T> c, int i) { + } + + public <T, R>R convertVarArgs(T t, Function<T, R> c, int... i) { + return null; + } + + public <T>void consumeVarArgs(T t, Consumer<T> c, int... i) { + } + + public <T, R>R convertVarArgs2(T t, Function<T, R>... c) { + return null; + } + + public <T>void consumeVarArgs2(T t, Consumer<T>... c) { + } + + public static class Test<T> { + + public Test() { + super(); + } + + public static <T>Test<T> of(T t) { + return new Test<>(); + } + + public <R>Test<R> convert(Function<T, R> c) { + return null; + } + + public void consume(Consumer<T> c) { + } + + public void consumeWithParam(Consumer<T> c, int i) { + } + } + + public interface Function<T, R> { + + public R map(T t); + } + + public interface Consumer<T> { + + public void run(T t); + } + }"""); + } + + private static void analyze(String fileName, String expectedAST) throws IOException { + try (StandardJavaFileManager fm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null)) { + List<JavaFileObject> files = new ArrayList<>(); + File source = new File(System.getProperty("test.src", "."), fileName.replace('/', File.separatorChar)).getAbsoluteFile(); + for (JavaFileObject f : fm.getJavaFileObjects(source)) { + files.add(f); + } + DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>(); + List<String> options = List.of("-source", JDK_VERSION, + "-XDshould-stop.at=FLOW"); + JavacTask ct = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, diagnostics, options, null, files); + Trees trees = Trees.instance(ct); + CompilationUnitTree cut = ct.parse().iterator().next(); + + ct.analyze(); + + String actualAST = Arrays.stream(cut.toString().split("\n")) + .map(l -> l.stripTrailing()) + .collect(Collectors.joining("\n")); + + if (!expectedAST.equals(actualAST)) { + throw new AssertionError("Unexpected AST shape!\n" + actualAST); + } + + Pattern p = Pattern.compile("/\\*getTypeMirror:(.*?)\\*/"); + Matcher m = p.matcher(cut.getSourceFile().getCharContent(false)); + + while (m.find()) { + TreePath tp = pathFor(trees, cut, m.start() - 1); + String expected = m.group(1); + if (expected.startsWith("getParentPath:")) { + tp = tp.getParentPath(); + expected = expected.substring("getParentPath:".length()); + } + TypeMirror found = trees.getTypeMirror(tp); + String actual = found != null ? found.getKind() + ":" + typeToString(found) : "<null>"; + + if (!expected.equals(actual)) { + throw new IllegalStateException("expected=" + expected + "; actual=" + actual + "; tree: " + tp.getLeaf()); + } + } + } + } + + private static TreePath pathFor(final Trees trees, final CompilationUnitTree cut, final int pos) { + final TreePath[] result = new TreePath[1]; + + new TreePathScanner<Void, Void>() { + @Override public Void scan(Tree node, Void p) { + if ( node != null + && trees.getSourcePositions().getStartPosition(cut, node) <= pos + && pos <= trees.getSourcePositions().getEndPosition(cut, node)) { + result[0] = new TreePath(getCurrentPath(), node); + return super.scan(node, p); + } + return null; + } + }.scan(cut, null); + + return result[0]; + } + + private static String typeToString(TypeMirror type) { + return type.toString(); + } + + static class TestFileObject extends SimpleJavaFileObject { + private final String text; + public TestFileObject(String text) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.text = text; + } + @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return text; + } + } + +} diff --git a/test/langtools/tools/javac/api/lambdaErrorRecovery/TestGetTypeMirrorReferenceData.java b/test/langtools/tools/javac/api/lambdaErrorRecovery/TestGetTypeMirrorReferenceData.java new file mode 100644 index 00000000000..28e62147bdf --- /dev/null +++ b/test/langtools/tools/javac/api/lambdaErrorRecovery/TestGetTypeMirrorReferenceData.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 test; + +public class TestGetTypeMirrorReferenceData { + + private static void test() { + Test.of(1).convert(c1 -> {Object o = c1/*getTypeMirror:DECLARED:java.lang.Integer*/;}); + Test.of(1).consume(c2 -> {Object o = c2/*getTypeMirror:DECLARED:java.lang.Integer*/; return null;}); + Test.of(1).consumeWithParam(c3 -> {Object o = c3/*getTypeMirror:DECLARED:java.lang.Integer*/;}); + convert(0, c4 -> {Object o = c4/*getTypeMirror:DECLARED:java.lang.Integer*/;}); + consume(0, c5 -> {Object o = c5/*getTypeMirror:DECLARED:java.lang.Integer*/;}); + convertVarArgs(0, c6 -> {Object o = c6/*getTypeMirror:DECLARED:java.lang.Integer*/;}, 1, 2, 3, 4); + consumeVarArgs(0, c7 -> {Object o = c7/*getTypeMirror:DECLARED:java.lang.Integer*/;}, 1, 2, 3, 4); + convertVarArgs2(0, c8 -> {Object o = c8/*getTypeMirror:DECLARED:java.lang.Integer*/;}, c8 -> {Object o = c8/*getTypeMirror:DECLARED:java.lang.Integer*/;}); + consumeVarArgs2(0, c9 -> {Object o = c9/*getTypeMirror:DECLARED:java.lang.Integer*/;}, c9 -> {Object o = c9/*getTypeMirror:DECLARED:java.lang.Integer*/;}); + } + public <T, R> R convert(T t, Function<T, R> f, int i) { + return null; + } + public <T> void consume(T t, Consumer<T> c, int i) { + } + public <T, R> R convertVarArgs(T t, Function<T, R> c, int... i) { + return null; + } + public <T> void consumeVarArgs(T t, Consumer<T> c, int... i) { + } + public <T, R> R convertVarArgs2(T t, Function<T, R>... c) { + return null; + } + public <T> void consumeVarArgs2(T t, Consumer<T>... c) { + } + public static class Test<T> { + public static <T> Test<T> of(T t) { + return new Test<>(); + } + public <R> Test<R> convert(Function<T, R> c) { + return null; + } + public void consume(Consumer<T> c) {} + public void consumeWithParam(Consumer<T> c, int i) {} + } + public interface Function<T, R> { + public R map(T t); + } + public interface Consumer<T> { + public void run(T t); + } +} diff --git a/test/langtools/tools/javac/diags/examples/DeconstructionPatternOnlyRecords.java b/test/langtools/tools/javac/diags/examples/DeconstructionPatternOnlyRecords.java new file mode 100644 index 00000000000..059cd038a26 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/DeconstructionPatternOnlyRecords.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.deconstruction.pattern.only.records +// key: compiler.warn.preview.feature.use.plural +// key: compiler.misc.feature.deconstruction.patterns +// options: --enable-preview -source ${jdk.version} -Xlint:preview + +class DeconstructionpatternOnlyRecords { + public boolean deconstruction(Object o) { + return o instanceof String(var content); + } +} diff --git a/test/langtools/tools/javac/diags/examples/IncorrectNumberOfNestedPatterns.java b/test/langtools/tools/javac/diags/examples/IncorrectNumberOfNestedPatterns.java new file mode 100644 index 00000000000..03949569e07 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/IncorrectNumberOfNestedPatterns.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.incorrect.number.of.nested.patterns +// key: compiler.misc.feature.deconstruction.patterns +// key: compiler.misc.feature.records +// key: compiler.warn.preview.feature.use.plural +// options: --enable-preview -source ${jdk.version} -Xlint:preview + +class IncorrectNumberOfNestedPatterns { + private boolean t(Object o) { + return o instanceof R(var i); + } + record R(int i, int j) {} +} diff --git a/test/langtools/tools/javac/diags/examples/UnderscoreAsIdentifierError.java b/test/langtools/tools/javac/diags/examples/UnderscoreAsIdentifierError.java index 1600d5cc2ca..9fa5fb4e8ec 100644 --- a/test/langtools/tools/javac/diags/examples/UnderscoreAsIdentifierError.java +++ b/test/langtools/tools/javac/diags/examples/UnderscoreAsIdentifierError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -22,6 +22,7 @@ */ // key: compiler.err.underscore.as.identifier +// options: -source 9 -Xlint:-options class UnderscoreAsIdentifierError { String _ = null; diff --git a/test/langtools/tools/javac/diags/examples/UnderscoreCantBeFollowedByDims.java b/test/langtools/tools/javac/diags/examples/UnderscoreCantBeFollowedByDims.java new file mode 100644 index 00000000000..851a8866c5b --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/UnderscoreCantBeFollowedByDims.java @@ -0,0 +1,29 @@ +/* + * 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. + */ + +// key: compiler.err.underscore.cant.be.followed.by.dimensions +// key: compiler.err.underscore.as.identifier.in.method + +class UnderscoreCantBeFollowedByDims { + void m(String _[]) {} +} diff --git a/test/langtools/tools/javac/diags/examples/UnderscoreInLambdaExpression.java b/test/langtools/tools/javac/diags/examples/UnderscoreInLambdaExpression.java index 586ab76a908..6616de5bd50 100644 --- a/test/langtools/tools/javac/diags/examples/UnderscoreInLambdaExpression.java +++ b/test/langtools/tools/javac/diags/examples/UnderscoreInLambdaExpression.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -22,6 +22,8 @@ */ // key: compiler.err.underscore.as.identifier.in.lambda +// options: -source 9 -Xlint:-options + public class UnderscoreInLambdaExpression { java.util.function.Function<String,String> f = _ -> "x"; } diff --git a/test/langtools/tools/javac/diags/examples/UnderscoreInMethodParameters.java b/test/langtools/tools/javac/diags/examples/UnderscoreInMethodParameters.java new file mode 100644 index 00000000000..be07733cea2 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/UnderscoreInMethodParameters.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +// key: compiler.err.underscore.as.identifier.in.method + +public class UnderscoreInMethodParameters { + void m(String _) {} +} diff --git a/test/langtools/tools/javac/diags/examples/UnderscoreOnlyInLamdaError.java b/test/langtools/tools/javac/diags/examples/UnderscoreOnlyInLamdaError.java new file mode 100644 index 00000000000..f51df461d4e --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/UnderscoreOnlyInLamdaError.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +// key: compiler.err.underscore.not.allowed + +import java.util.function.*; + +class UnderscoreAsIdentifierError { + BiFunction<Integer, String, String> biss = (i, j) -> String.valueOf(_); +} diff --git a/test/langtools/tools/javac/lambda/IdentifierTest.java b/test/langtools/tools/javac/lambda/IdentifierTest.java index d4025fff825..b7ded314c1f 100644 --- a/test/langtools/tools/javac/lambda/IdentifierTest.java +++ b/test/langtools/tools/javac/lambda/IdentifierTest.java @@ -4,7 +4,8 @@ * @author sogoel * @summary Test generation of warnings when '_' is used an identifier * @compile/fail/ref=IdentifierTest8.out -source 8 -Xlint:-options -Werror -XDrawDiagnostics IdentifierTest.java - * @compile/fail/ref=IdentifierTest9.out -XDrawDiagnostics IdentifierTest.java + * @compile/fail/ref=IdentifierTest9.out -source 9 -Xlint:-options -XDrawDiagnostics IdentifierTest.java + * @compile/fail/ref=IdentifierTest10.out -Xlint:-options -XDrawDiagnostics IdentifierTest.java */ import java.util.List; @@ -180,4 +181,3 @@ public void testLabels() { interface _ { void mI(); } - diff --git a/test/langtools/tools/javac/lambda/IdentifierTest10.out b/test/langtools/tools/javac/lambda/IdentifierTest10.out new file mode 100644 index 00000000000..421acad2ae6 --- /dev/null +++ b/test/langtools/tools/javac/lambda/IdentifierTest10.out @@ -0,0 +1,44 @@ +IdentifierTest.java:42:11: compiler.err.underscore.not.allowed +IdentifierTest.java:45:16: compiler.err.underscore.not.allowed +IdentifierTest.java:46:20: compiler.err.underscore.not.allowed +IdentifierTest.java:47:22: compiler.err.underscore.not.allowed +IdentifierTest.java:52:13: compiler.err.underscore.not.allowed +IdentifierTest.java:52:15: compiler.err.underscore.not.allowed +IdentifierTest.java:52:23: compiler.err.underscore.not.allowed +IdentifierTest.java:54:13: compiler.err.underscore.not.allowed +IdentifierTest.java:56:13: compiler.err.underscore.not.allowed +IdentifierTest.java:62:21: compiler.err.underscore.not.allowed +IdentifierTest.java:64:67: compiler.err.underscore.not.allowed +IdentifierTest.java:71:13: compiler.err.underscore.not.allowed +IdentifierTest.java:72:14: compiler.err.underscore.not.allowed +IdentifierTest.java:73:18: compiler.err.underscore.not.allowed +IdentifierTest.java:78:22: compiler.err.underscore.not.allowed +IdentifierTest.java:80:13: compiler.err.underscore.not.allowed +IdentifierTest.java:80:15: compiler.err.underscore.not.allowed +IdentifierTest.java:82:13: compiler.err.underscore.not.allowed +IdentifierTest.java:82:15: compiler.err.underscore.not.allowed +IdentifierTest.java:89:10: compiler.err.underscore.not.allowed +IdentifierTest.java:89:38: compiler.err.underscore.not.allowed +IdentifierTest.java:95:14: compiler.err.underscore.not.allowed +IdentifierTest.java:102:17: compiler.err.underscore.not.allowed +IdentifierTest.java:102:26: compiler.err.underscore.not.allowed +IdentifierTest.java:119:20: compiler.err.underscore.not.allowed +IdentifierTest.java:124:10: compiler.err.underscore.not.allowed +IdentifierTest.java:129:17: compiler.err.underscore.not.allowed +IdentifierTest.java:132:17: compiler.err.underscore.not.allowed +IdentifierTest.java:139:17: compiler.err.underscore.not.allowed +IdentifierTest.java:139:24: compiler.err.underscore.not.allowed +IdentifierTest.java:139:33: compiler.err.underscore.not.allowed +IdentifierTest.java:140:39: compiler.err.underscore.not.allowed +IdentifierTest.java:144:13: compiler.err.underscore.not.allowed +IdentifierTest.java:145:15: compiler.err.underscore.not.allowed +IdentifierTest.java:146:13: compiler.err.underscore.not.allowed +IdentifierTest.java:151:15: compiler.err.underscore.not.allowed +IdentifierTest.java:152:17: compiler.err.underscore.not.allowed +IdentifierTest.java:158:16: compiler.err.underscore.not.allowed +IdentifierTest.java:160:25: compiler.err.underscore.not.allowed +IdentifierTest.java:169:5: compiler.err.underscore.not.allowed +IdentifierTest.java:173:26: compiler.err.underscore.not.allowed +IdentifierTest.java:175:19: compiler.err.underscore.not.allowed +IdentifierTest.java:181:11: compiler.err.underscore.not.allowed +43 errors diff --git a/test/langtools/tools/javac/lambda/IdentifierTest8.out b/test/langtools/tools/javac/lambda/IdentifierTest8.out index 6d1da256d40..2a570598c35 100644 --- a/test/langtools/tools/javac/lambda/IdentifierTest8.out +++ b/test/langtools/tools/javac/lambda/IdentifierTest8.out @@ -1,47 +1,47 @@ -IdentifierTest.java:41:11: compiler.warn.underscore.as.identifier -IdentifierTest.java:44:16: compiler.warn.underscore.as.identifier -IdentifierTest.java:45:20: compiler.warn.underscore.as.identifier -IdentifierTest.java:46:22: compiler.warn.underscore.as.identifier -IdentifierTest.java:51:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:51:15: compiler.warn.underscore.as.identifier -IdentifierTest.java:51:23: compiler.warn.underscore.as.identifier -IdentifierTest.java:53:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:55:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:61:21: compiler.warn.underscore.as.identifier -IdentifierTest.java:62:42: compiler.warn.underscore.as.identifier -IdentifierTest.java:63:67: compiler.warn.underscore.as.identifier -IdentifierTest.java:70:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:71:14: compiler.warn.underscore.as.identifier -IdentifierTest.java:72:18: compiler.warn.underscore.as.identifier -IdentifierTest.java:77:22: compiler.warn.underscore.as.identifier -IdentifierTest.java:79:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:79:15: compiler.warn.underscore.as.identifier -IdentifierTest.java:81:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:81:15: compiler.warn.underscore.as.identifier -IdentifierTest.java:88:10: compiler.warn.underscore.as.identifier -IdentifierTest.java:88:38: compiler.warn.underscore.as.identifier -IdentifierTest.java:94:14: compiler.warn.underscore.as.identifier -IdentifierTest.java:101:17: compiler.warn.underscore.as.identifier -IdentifierTest.java:101:26: compiler.warn.underscore.as.identifier -IdentifierTest.java:118:20: compiler.warn.underscore.as.identifier -IdentifierTest.java:123:10: compiler.warn.underscore.as.identifier -IdentifierTest.java:128:17: compiler.warn.underscore.as.identifier -IdentifierTest.java:131:17: compiler.warn.underscore.as.identifier -IdentifierTest.java:138:17: compiler.warn.underscore.as.identifier -IdentifierTest.java:138:24: compiler.warn.underscore.as.identifier -IdentifierTest.java:138:33: compiler.warn.underscore.as.identifier -IdentifierTest.java:139:39: compiler.warn.underscore.as.identifier -IdentifierTest.java:143:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:144:15: compiler.warn.underscore.as.identifier -IdentifierTest.java:145:13: compiler.warn.underscore.as.identifier -IdentifierTest.java:150:15: compiler.warn.underscore.as.identifier -IdentifierTest.java:151:17: compiler.warn.underscore.as.identifier -IdentifierTest.java:157:16: compiler.warn.underscore.as.identifier -IdentifierTest.java:159:25: compiler.warn.underscore.as.identifier -IdentifierTest.java:168:5: compiler.warn.underscore.as.identifier -IdentifierTest.java:172:26: compiler.warn.underscore.as.identifier -IdentifierTest.java:174:19: compiler.warn.underscore.as.identifier -IdentifierTest.java:180:11: compiler.warn.underscore.as.identifier +IdentifierTest.java:42:11: compiler.warn.underscore.as.identifier +IdentifierTest.java:45:16: compiler.warn.underscore.as.identifier +IdentifierTest.java:46:20: compiler.warn.underscore.as.identifier +IdentifierTest.java:47:22: compiler.warn.underscore.as.identifier +IdentifierTest.java:52:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:52:15: compiler.warn.underscore.as.identifier +IdentifierTest.java:52:23: compiler.warn.underscore.as.identifier +IdentifierTest.java:54:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:56:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:62:21: compiler.warn.underscore.as.identifier +IdentifierTest.java:63:42: compiler.warn.underscore.as.identifier +IdentifierTest.java:64:67: compiler.warn.underscore.as.identifier +IdentifierTest.java:71:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:72:14: compiler.warn.underscore.as.identifier +IdentifierTest.java:73:18: compiler.warn.underscore.as.identifier +IdentifierTest.java:78:22: compiler.warn.underscore.as.identifier +IdentifierTest.java:80:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:80:15: compiler.warn.underscore.as.identifier +IdentifierTest.java:82:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:82:15: compiler.warn.underscore.as.identifier +IdentifierTest.java:89:10: compiler.warn.underscore.as.identifier +IdentifierTest.java:89:38: compiler.warn.underscore.as.identifier +IdentifierTest.java:95:14: compiler.warn.underscore.as.identifier +IdentifierTest.java:102:17: compiler.warn.underscore.as.identifier +IdentifierTest.java:102:26: compiler.warn.underscore.as.identifier +IdentifierTest.java:119:20: compiler.warn.underscore.as.identifier +IdentifierTest.java:124:10: compiler.warn.underscore.as.identifier +IdentifierTest.java:129:17: compiler.warn.underscore.as.identifier +IdentifierTest.java:132:17: compiler.warn.underscore.as.identifier +IdentifierTest.java:139:17: compiler.warn.underscore.as.identifier +IdentifierTest.java:139:24: compiler.warn.underscore.as.identifier +IdentifierTest.java:139:33: compiler.warn.underscore.as.identifier +IdentifierTest.java:140:39: compiler.warn.underscore.as.identifier +IdentifierTest.java:144:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:145:15: compiler.warn.underscore.as.identifier +IdentifierTest.java:146:13: compiler.warn.underscore.as.identifier +IdentifierTest.java:151:15: compiler.warn.underscore.as.identifier +IdentifierTest.java:152:17: compiler.warn.underscore.as.identifier +IdentifierTest.java:158:16: compiler.warn.underscore.as.identifier +IdentifierTest.java:160:25: compiler.warn.underscore.as.identifier +IdentifierTest.java:169:5: compiler.warn.underscore.as.identifier +IdentifierTest.java:173:26: compiler.warn.underscore.as.identifier +IdentifierTest.java:175:19: compiler.warn.underscore.as.identifier +IdentifierTest.java:181:11: compiler.warn.underscore.as.identifier - compiler.err.warnings.and.werror 1 error 44 warnings diff --git a/test/langtools/tools/javac/lambda/IdentifierTest9.out b/test/langtools/tools/javac/lambda/IdentifierTest9.out index 6dd260aa8a2..7ee6c8cb149 100644 --- a/test/langtools/tools/javac/lambda/IdentifierTest9.out +++ b/test/langtools/tools/javac/lambda/IdentifierTest9.out @@ -1,45 +1,45 @@ -IdentifierTest.java:41:11: compiler.err.underscore.as.identifier -IdentifierTest.java:44:16: compiler.err.underscore.as.identifier -IdentifierTest.java:45:20: compiler.err.underscore.as.identifier -IdentifierTest.java:46:22: compiler.err.underscore.as.identifier -IdentifierTest.java:51:13: compiler.err.underscore.as.identifier -IdentifierTest.java:51:15: compiler.err.underscore.as.identifier -IdentifierTest.java:51:23: compiler.err.underscore.as.identifier -IdentifierTest.java:53:13: compiler.err.underscore.as.identifier -IdentifierTest.java:55:13: compiler.err.underscore.as.identifier -IdentifierTest.java:61:21: compiler.err.underscore.as.identifier -IdentifierTest.java:62:42: compiler.err.underscore.as.identifier -IdentifierTest.java:63:67: compiler.err.underscore.as.identifier -IdentifierTest.java:70:13: compiler.err.underscore.as.identifier -IdentifierTest.java:71:14: compiler.err.underscore.as.identifier -IdentifierTest.java:72:18: compiler.err.underscore.as.identifier -IdentifierTest.java:77:22: compiler.err.underscore.as.identifier -IdentifierTest.java:79:13: compiler.err.underscore.as.identifier -IdentifierTest.java:79:15: compiler.err.underscore.as.identifier -IdentifierTest.java:81:13: compiler.err.underscore.as.identifier -IdentifierTest.java:81:15: compiler.err.underscore.as.identifier -IdentifierTest.java:88:10: compiler.err.underscore.as.identifier -IdentifierTest.java:88:38: compiler.err.underscore.as.identifier -IdentifierTest.java:94:14: compiler.err.underscore.as.identifier -IdentifierTest.java:101:17: compiler.err.underscore.as.identifier -IdentifierTest.java:101:26: compiler.err.underscore.as.identifier -IdentifierTest.java:118:20: compiler.err.underscore.as.identifier -IdentifierTest.java:123:10: compiler.err.underscore.as.identifier -IdentifierTest.java:128:17: compiler.err.underscore.as.identifier -IdentifierTest.java:131:17: compiler.err.underscore.as.identifier -IdentifierTest.java:138:17: compiler.err.underscore.as.identifier -IdentifierTest.java:138:24: compiler.err.underscore.as.identifier -IdentifierTest.java:138:33: compiler.err.underscore.as.identifier -IdentifierTest.java:139:39: compiler.err.underscore.as.identifier -IdentifierTest.java:143:13: compiler.err.underscore.as.identifier -IdentifierTest.java:144:15: compiler.err.underscore.as.identifier -IdentifierTest.java:145:13: compiler.err.underscore.as.identifier -IdentifierTest.java:150:15: compiler.err.underscore.as.identifier -IdentifierTest.java:151:17: compiler.err.underscore.as.identifier -IdentifierTest.java:157:16: compiler.err.underscore.as.identifier -IdentifierTest.java:159:25: compiler.err.underscore.as.identifier -IdentifierTest.java:168:5: compiler.err.underscore.as.identifier -IdentifierTest.java:172:26: compiler.err.underscore.as.identifier -IdentifierTest.java:174:19: compiler.err.underscore.as.identifier -IdentifierTest.java:180:11: compiler.err.underscore.as.identifier +IdentifierTest.java:42:11: compiler.err.underscore.as.identifier +IdentifierTest.java:45:16: compiler.err.underscore.as.identifier +IdentifierTest.java:46:20: compiler.err.underscore.as.identifier +IdentifierTest.java:47:22: compiler.err.underscore.as.identifier +IdentifierTest.java:52:13: compiler.err.underscore.as.identifier +IdentifierTest.java:52:15: compiler.err.underscore.as.identifier +IdentifierTest.java:52:23: compiler.err.underscore.as.identifier +IdentifierTest.java:54:13: compiler.err.underscore.as.identifier +IdentifierTest.java:56:13: compiler.err.underscore.as.identifier +IdentifierTest.java:62:21: compiler.err.underscore.as.identifier +IdentifierTest.java:63:42: compiler.err.underscore.as.identifier +IdentifierTest.java:64:67: compiler.err.underscore.as.identifier +IdentifierTest.java:71:13: compiler.err.underscore.as.identifier +IdentifierTest.java:72:14: compiler.err.underscore.as.identifier +IdentifierTest.java:73:18: compiler.err.underscore.as.identifier +IdentifierTest.java:78:22: compiler.err.underscore.as.identifier +IdentifierTest.java:80:13: compiler.err.underscore.as.identifier +IdentifierTest.java:80:15: compiler.err.underscore.as.identifier +IdentifierTest.java:82:13: compiler.err.underscore.as.identifier +IdentifierTest.java:82:15: compiler.err.underscore.as.identifier +IdentifierTest.java:89:10: compiler.err.underscore.as.identifier +IdentifierTest.java:89:38: compiler.err.underscore.as.identifier +IdentifierTest.java:95:14: compiler.err.underscore.as.identifier +IdentifierTest.java:102:17: compiler.err.underscore.as.identifier +IdentifierTest.java:102:26: compiler.err.underscore.as.identifier +IdentifierTest.java:119:20: compiler.err.underscore.as.identifier +IdentifierTest.java:124:10: compiler.err.underscore.as.identifier +IdentifierTest.java:129:17: compiler.err.underscore.as.identifier +IdentifierTest.java:132:17: compiler.err.underscore.as.identifier +IdentifierTest.java:139:17: compiler.err.underscore.as.identifier +IdentifierTest.java:139:24: compiler.err.underscore.as.identifier +IdentifierTest.java:139:33: compiler.err.underscore.as.identifier +IdentifierTest.java:140:39: compiler.err.underscore.as.identifier +IdentifierTest.java:144:13: compiler.err.underscore.as.identifier +IdentifierTest.java:145:15: compiler.err.underscore.as.identifier +IdentifierTest.java:146:13: compiler.err.underscore.as.identifier +IdentifierTest.java:151:15: compiler.err.underscore.as.identifier +IdentifierTest.java:152:17: compiler.err.underscore.as.identifier +IdentifierTest.java:158:16: compiler.err.underscore.as.identifier +IdentifierTest.java:160:25: compiler.err.underscore.as.identifier +IdentifierTest.java:169:5: compiler.err.underscore.as.identifier +IdentifierTest.java:173:26: compiler.err.underscore.as.identifier +IdentifierTest.java:175:19: compiler.err.underscore.as.identifier +IdentifierTest.java:181:11: compiler.err.underscore.as.identifier 44 errors diff --git a/test/langtools/tools/javac/lambda/LambdaParserTest.java b/test/langtools/tools/javac/lambda/LambdaParserTest.java index e3440d3b17f..02ff762c005 100644 --- a/test/langtools/tools/javac/lambda/LambdaParserTest.java +++ b/test/langtools/tools/javac/lambda/LambdaParserTest.java @@ -295,7 +295,7 @@ void check(Result<?> res) { } errorExpected |= pn == LambdaParameterName.UNDERSCORE && - lk.arity() > 0; + lk.arity() > 0 && sk == SourceKind.SOURCE_9; for (int i = 0; i < lk.arity(); i++) { if (!lk.isShort() && diff --git a/test/langtools/tools/javac/lambda/LambdaScope04.java b/test/langtools/tools/javac/lambda/LambdaScope04.java index a2ebc6f28d5..c42b2342a4e 100644 --- a/test/langtools/tools/javac/lambda/LambdaScope04.java +++ b/test/langtools/tools/javac/lambda/LambdaScope04.java @@ -3,7 +3,8 @@ * @bug 8003280 * @summary Add lambda tests * check that lambda cannot shadow variables from enclosing scope - * @compile/fail/ref=LambdaScope04.out -XDrawDiagnostics LambdaScope04.java + * @compile/fail/ref=LambdaScope04_Source9.out -source 9 -Xlint:-options -XDrawDiagnostics LambdaScope04.java + * @compile/fail/ref=LambdaScope04_Source10.out -Xlint:-options -XDrawDiagnostics LambdaScope04.java */ class LambdaScope04 { diff --git a/test/langtools/tools/javac/lambda/LambdaScope04_Source10.out b/test/langtools/tools/javac/lambda/LambdaScope04_Source10.out new file mode 100644 index 00000000000..74535a253c5 --- /dev/null +++ b/test/langtools/tools/javac/lambda/LambdaScope04_Source10.out @@ -0,0 +1,3 @@ +LambdaScope04.java:110:28: compiler.err.unreported.exception.implicit.close: java.lang.Exception, local +LambdaScope04.java:118:28: compiler.err.unreported.exception.implicit.close: java.lang.Exception, local +2 errors diff --git a/test/langtools/tools/javac/lambda/LambdaScope04.out b/test/langtools/tools/javac/lambda/LambdaScope04_Source9.out similarity index 52% rename from test/langtools/tools/javac/lambda/LambdaScope04.out rename to test/langtools/tools/javac/lambda/LambdaScope04_Source9.out index 8cb2e2ab242..d474f8bf0c7 100644 --- a/test/langtools/tools/javac/lambda/LambdaScope04.out +++ b/test/langtools/tools/javac/lambda/LambdaScope04_Source9.out @@ -1,37 +1,37 @@ -LambdaScope04.java:23:18: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.instance.init, kindname.class, LambdaScope04 -LambdaScope04.java:24:34: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.instance.init, kindname.class, LambdaScope04 -LambdaScope04.java:29:18: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.static.init, kindname.class, LambdaScope04 -LambdaScope04.java:30:34: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.static.init, kindname.class, LambdaScope04 -LambdaScope04.java:36:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalInstance() -LambdaScope04.java:37:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalInstance() -LambdaScope04.java:43:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalStatic() -LambdaScope04.java:44:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalStatic() -LambdaScope04.java:49:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamInstance(java.lang.Object) -LambdaScope04.java:50:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamInstance(java.lang.Object) -LambdaScope04.java:55:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamStatic(java.lang.Object) -LambdaScope04.java:56:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamStatic(java.lang.Object) -LambdaScope04.java:62:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForInstance() -LambdaScope04.java:63:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForInstance() -LambdaScope04.java:70:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForStatic(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:71:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForStatic(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:78:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachInstance(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:79:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachInstance(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:86:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachStatic(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:87:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachStatic(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:94:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchInstance() -LambdaScope04.java:95:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchInstance() -LambdaScope04.java:102:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchStatic(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:103:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchStatic(java.lang.Iterable<java.lang.Object>) -LambdaScope04.java:110:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRInstance(java.lang.AutoCloseable) -LambdaScope04.java:111:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRInstance(java.lang.AutoCloseable) -LambdaScope04.java:118:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRStatic(java.lang.AutoCloseable) -LambdaScope04.java:119:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRStatic(java.lang.AutoCloseable) -LambdaScope04.java:127:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalInstance() -LambdaScope04.java:128:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalInstance() -LambdaScope04.java:136:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalStatic() -LambdaScope04.java:137:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalStatic() -LambdaScope04.java:146:26: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalInstance(int) -LambdaScope04.java:147:42: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalInstance(int) -LambdaScope04.java:157:26: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalStatic(int) -LambdaScope04.java:158:42: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalStatic(int) +LambdaScope04.java:24:18: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.instance.init, kindname.class, LambdaScope04 +LambdaScope04.java:25:34: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.instance.init, kindname.class, LambdaScope04 +LambdaScope04.java:30:18: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.static.init, kindname.class, LambdaScope04 +LambdaScope04.java:31:34: compiler.err.already.defined.in.clinit: kindname.variable, local, kindname.static.init, kindname.class, LambdaScope04 +LambdaScope04.java:37:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalInstance() +LambdaScope04.java:38:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalInstance() +LambdaScope04.java:44:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalStatic() +LambdaScope04.java:45:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testLocalStatic() +LambdaScope04.java:50:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamInstance(java.lang.Object) +LambdaScope04.java:51:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamInstance(java.lang.Object) +LambdaScope04.java:56:18: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamStatic(java.lang.Object) +LambdaScope04.java:57:34: compiler.err.already.defined: kindname.variable, local, kindname.method, testParamStatic(java.lang.Object) +LambdaScope04.java:63:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForInstance() +LambdaScope04.java:64:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForInstance() +LambdaScope04.java:71:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForStatic(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:72:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForStatic(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:79:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachInstance(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:80:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachInstance(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:87:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachStatic(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:88:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testForEachStatic(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:95:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchInstance() +LambdaScope04.java:96:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchInstance() +LambdaScope04.java:103:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchStatic(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:104:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testCatchStatic(java.lang.Iterable<java.lang.Object>) +LambdaScope04.java:111:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRInstance(java.lang.AutoCloseable) +LambdaScope04.java:112:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRInstance(java.lang.AutoCloseable) +LambdaScope04.java:119:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRStatic(java.lang.AutoCloseable) +LambdaScope04.java:120:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testTWRStatic(java.lang.AutoCloseable) +LambdaScope04.java:128:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalInstance() +LambdaScope04.java:129:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalInstance() +LambdaScope04.java:137:22: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalStatic() +LambdaScope04.java:138:38: compiler.err.already.defined: kindname.variable, local, kindname.method, testBlockLocalStatic() +LambdaScope04.java:147:26: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalInstance(int) +LambdaScope04.java:148:42: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalInstance(int) +LambdaScope04.java:158:26: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalStatic(int) +LambdaScope04.java:159:42: compiler.err.already.defined: kindname.variable, local, kindname.method, testSwitchLocalStatic(int) 36 errors diff --git a/test/langtools/tools/javac/lambda/LambdaScope05.java b/test/langtools/tools/javac/lambda/LambdaScope05.java index 0fbb4a20576..e3678b97a93 100644 --- a/test/langtools/tools/javac/lambda/LambdaScope05.java +++ b/test/langtools/tools/javac/lambda/LambdaScope05.java @@ -2,7 +2,8 @@ * @test /nodynamiccopyright/ * @bug 8015648 * @summary Duplicate variable in lambda causes javac crash - * @compile/fail/ref=LambdaScope05.out -XDrawDiagnostics LambdaScope05.java + * @compile/fail/ref=LambdaScope05_Source9.out -source 9 -Xlint:-options -XDrawDiagnostics LambdaScope05.java + * @compile -source 10 -Xlint:-options -XDrawDiagnostics LambdaScope05.java */ class LambdaScope05 { diff --git a/test/langtools/tools/javac/lambda/LambdaScope05.out b/test/langtools/tools/javac/lambda/LambdaScope05.out deleted file mode 100644 index e96b9e5aad8..00000000000 --- a/test/langtools/tools/javac/lambda/LambdaScope05.out +++ /dev/null @@ -1,7 +0,0 @@ -LambdaScope05.java:13:47: compiler.err.already.defined.in.clinit: kindname.variable, p, kindname.static.init, kindname.class, LambdaScope05 -LambdaScope05.java:14:40: compiler.err.already.defined: kindname.variable, p, kindname.constructor, LambdaScope05() -LambdaScope05.java:17:43: compiler.err.already.defined.in.clinit: kindname.variable, p, kindname.static.init, kindname.class, LambdaScope05 -LambdaScope05.java:21:43: compiler.err.already.defined.in.clinit: kindname.variable, p, kindname.instance.init, kindname.class, LambdaScope05 -LambdaScope05.java:25:43: compiler.err.already.defined: kindname.variable, p, kindname.method, m_static() -LambdaScope05.java:29:43: compiler.err.already.defined: kindname.variable, p, kindname.method, m() -6 errors diff --git a/test/langtools/tools/javac/lambda/LambdaScope05_Source9.out b/test/langtools/tools/javac/lambda/LambdaScope05_Source9.out new file mode 100644 index 00000000000..49e1cbfc12c --- /dev/null +++ b/test/langtools/tools/javac/lambda/LambdaScope05_Source9.out @@ -0,0 +1,7 @@ +LambdaScope05.java:14:47: compiler.err.already.defined.in.clinit: kindname.variable, p, kindname.static.init, kindname.class, LambdaScope05 +LambdaScope05.java:15:40: compiler.err.already.defined: kindname.variable, p, kindname.constructor, LambdaScope05() +LambdaScope05.java:18:43: compiler.err.already.defined.in.clinit: kindname.variable, p, kindname.static.init, kindname.class, LambdaScope05 +LambdaScope05.java:22:43: compiler.err.already.defined.in.clinit: kindname.variable, p, kindname.instance.init, kindname.class, LambdaScope05 +LambdaScope05.java:26:43: compiler.err.already.defined: kindname.variable, p, kindname.method, m_static() +LambdaScope05.java:30:43: compiler.err.already.defined: kindname.variable, p, kindname.method, m() +6 errors diff --git a/test/langtools/tools/javac/lambda/UnderscoreAsIdent.java b/test/langtools/tools/javac/lambda/UnderscoreAsIdent.java index dc50aa143e0..e18c9de9c75 100644 --- a/test/langtools/tools/javac/lambda/UnderscoreAsIdent.java +++ b/test/langtools/tools/javac/lambda/UnderscoreAsIdent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -25,7 +25,7 @@ * @test * @summary Check usages of underscore as identifier generate warnings * @compile/fail/ref=UnderscoreAsIdent8.out -source 8 -Xlint:-options -XDrawDiagnostics -Werror UnderscoreAsIdent.java - * @compile/fail/ref=UnderscoreAsIdent9.out -XDrawDiagnostics -Werror UnderscoreAsIdent.java + * @compile/fail/ref=UnderscoreAsIdent9.out -source 9 -Xlint:-options -XDrawDiagnostics -Werror UnderscoreAsIdent.java */ package _._; diff --git a/test/langtools/tools/javac/lambda/deduplication/Deduplication.java b/test/langtools/tools/javac/lambda/deduplication/Deduplication.java index d56f5127980..2b9a5e82b91 100644 --- a/test/langtools/tools/javac/lambda/deduplication/Deduplication.java +++ b/test/langtools/tools/javac/lambda/deduplication/Deduplication.java @@ -166,6 +166,12 @@ void f() {} group((Function<Object, Integer>) x -> x instanceof Integer i ? i : -1, (Function<Object, Integer>) x -> x instanceof Integer i ? i : -1); + + group((Function<Object, Integer>) x -> x instanceof R(var i1, var i2) ? i1 : -1, + (Function<Object, Integer>) x -> x instanceof R(var i1, var i2) ? i1 : -1 ); + + group((Function<Object, Integer>) x -> x instanceof R(Integer i1, int i2) ? i2 : -1, + (Function<Object, Integer>) x -> x instanceof R(Integer i1, int i2) ? i2 : -1 ); } void f() {} @@ -174,4 +180,6 @@ void g() {} int i; int j; + + record R(Integer i1, int i2) {} } diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java b/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java index 5152d89a069..32f9a6a9c72 100644 --- a/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java +++ b/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java @@ -134,6 +134,9 @@ public static void main(String[] args) throws Exception { Set<String> bootstrapMethodNames = new TreeSet<>(); for (JavaFileObject output : generated) { ClassFile cf = ClassFile.read(output.openInputStream()); + if (cf.getName().equals("com/sun/tools/javac/comp/Deduplication$R")) { + continue; + } BootstrapMethods_attribute bsm = (BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods); for (BootstrapMethodSpecifier b : bsm.bootstrap_method_specifiers) { diff --git a/test/langtools/tools/javac/lambda_leftovers/ShadowParametersTest01.java b/test/langtools/tools/javac/lambda_leftovers/ShadowParametersTest01.java new file mode 100644 index 00000000000..71e3a515780 --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/ShadowParametersTest01.java @@ -0,0 +1,39 @@ +/* + * 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 8173061 + * @summary Shadowing of lambda parameters + * @compile ShadowParametersTest01.java + */ + +import java.util.*; + +public class ShadowParametersTest01 { + void foo() { + Map<String, Integer> msi = null; + String key = "333"; + msi.computeIfAbsent(key, key -> key.length()); + } +} diff --git a/test/langtools/tools/javac/lambda_leftovers/ShadowParametersTest02.java b/test/langtools/tools/javac/lambda_leftovers/ShadowParametersTest02.java new file mode 100644 index 00000000000..76f6267de5d --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/ShadowParametersTest02.java @@ -0,0 +1,60 @@ +/* + * 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 8173061 + * @summary Shadowing of lambda parameters + * @modules jdk.compiler/com.sun.tools.javac.util + * @run main ShadowParametersTest02 + */ + +import com.sun.tools.javac.util.Assert; + +public class ShadowParametersTest02 { + public static void main(String... args) { + new ShadowParametersTest02().tests(); + } + + void tests() { + m(1); + Assert.check(str.equals("Hi from lambda")); + Assert.check(b); + } + + String str = null; + boolean b = false; + + void m(int x) { + Runnable r = () -> { + String x = "Hi from lambda"; + str = x; + Runnable r = () -> { + boolean x = true; + b = x; + }; + r.run(); + }; + r.run(); + } +} diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreCantBeFollowedByDimsTest.java b/test/langtools/tools/javac/lambda_leftovers/UnderscoreCantBeFollowedByDimsTest.java new file mode 100644 index 00000000000..feff3cec230 --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreCantBeFollowedByDimsTest.java @@ -0,0 +1,10 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8177513 + * @summary underscore can't be followed by dimensions + * @compile/fail/ref=UnderscoreCantBeFollowedByDimsTest.out -XDrawDiagnostics UnderscoreCantBeFollowedByDimsTest.java + */ + +public class UnderscoreCantBeFollowedByDimsTest { + void m(String _[]) {} +} diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreCantBeFollowedByDimsTest.out b/test/langtools/tools/javac/lambda_leftovers/UnderscoreCantBeFollowedByDimsTest.out new file mode 100644 index 00000000000..505636f7580 --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreCantBeFollowedByDimsTest.out @@ -0,0 +1,3 @@ +UnderscoreCantBeFollowedByDimsTest.java:9:19: compiler.err.underscore.as.identifier.in.method +UnderscoreCantBeFollowedByDimsTest.java:9:20: compiler.err.underscore.cant.be.followed.by.dimensions +2 errors diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreInCatchClauseTest.java b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInCatchClauseTest.java new file mode 100644 index 00000000000..02722f90313 --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInCatchClauseTest.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8173059 + * @summary Underscore for unnamed method, constructor, lambda, and catch formals + * @compile/fail/ref=UnderscoreInCatchClauseTest.out -XDrawDiagnostics UnderscoreInCatchClauseTest.java + */ + +public class UnderscoreInCatchClauseTest { + void foo() { + // this use should be allowed + try { } catch (Throwable _) { + // this use should be forbidden + throw _; + } + } +} diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreInCatchClauseTest.out b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInCatchClauseTest.out new file mode 100644 index 00000000000..9e73b28be74 --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInCatchClauseTest.out @@ -0,0 +1,2 @@ +UnderscoreInCatchClauseTest.java:13:19: compiler.err.underscore.not.allowed +1 error diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreInLambdaTest.java b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInLambdaTest.java new file mode 100644 index 00000000000..20f77a1de2b --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInLambdaTest.java @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8173059 + * @summary Underscore for unnamed method, constructor, lambda, and catch formals + * @compile/fail/ref=UnderscoreInLambdaTest.out -XDrawDiagnostics UnderscoreInLambdaTest.java + */ + +import java.util.function.*; + +public class UnderscoreInLambdaTest { + void foo() { + // error + BiFunction<Integer, String, String> biss1 = + (_, _) -> + String.valueOf(_); // this use will be detected and banned by the parser + // ok implicit + BiFunction<Integer, String, String> biss2 = + (_, _) -> ""; + // ok explicit + BiFunction<Integer, String, String> biss2 = + (int _, String _) -> ""; + } +} diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreInLambdaTest.out b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInLambdaTest.out new file mode 100644 index 00000000000..c59792516fd --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInLambdaTest.out @@ -0,0 +1,2 @@ +UnderscoreInLambdaTest.java:15:36: compiler.err.underscore.not.allowed +1 error diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreInMethodsTest.java b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInMethodsTest.java new file mode 100644 index 00000000000..221984cd281 --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInMethodsTest.java @@ -0,0 +1,19 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8173059 + * @summary Underscore for unnamed method, constructor, lambda, and catch formals + * @compile/fail/ref=UnderscoreInMethodsTest.out -XDrawDiagnostics UnderscoreInMethodsTest.java + */ + +public class UnderscoreInMethodsTest { + class Super { + void m(String _) {} + } + + class Child extends Super { + void m(String _) { + // error '_' is not in scope so it can't be used inside the method + System.out.println(_); + } + } +} diff --git a/test/langtools/tools/javac/lambda_leftovers/UnderscoreInMethodsTest.out b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInMethodsTest.out new file mode 100644 index 00000000000..1fc88c43f3f --- /dev/null +++ b/test/langtools/tools/javac/lambda_leftovers/UnderscoreInMethodsTest.out @@ -0,0 +1,4 @@ +UnderscoreInMethodsTest.java:10:23: compiler.err.underscore.as.identifier.in.method +UnderscoreInMethodsTest.java:14:23: compiler.err.underscore.as.identifier.in.method +UnderscoreInMethodsTest.java:16:32: compiler.err.underscore.not.allowed +3 errors diff --git a/test/langtools/tools/javac/lvti/SelfRefTest.java b/test/langtools/tools/javac/lvti/SelfRefTest.java index 98f956d96b2..e04b38e2b12 100644 --- a/test/langtools/tools/javac/lvti/SelfRefTest.java +++ b/test/langtools/tools/javac/lvti/SelfRefTest.java @@ -14,7 +14,7 @@ class SelfRefTest { void test(boolean cond) { var x = cond ? x : x; //error - self reference - var y = (Function<Integer, Integer>)(Integer y) -> y; //error - bad shadowing + var y = (Function<Integer, Integer>)(Integer y) -> y; //error - bad shadowing - but ok in lambda leftovers! var z = (Runnable)() -> { int z2 = m(z); }; //error - self reference var w = new Object() { int w = 42; void test() { int w2 = w; } }; //ok int u = u; //ok diff --git a/test/langtools/tools/javac/lvti/SelfRefTest.out b/test/langtools/tools/javac/lvti/SelfRefTest.out index 97a558c4543..5a01ee70d40 100644 --- a/test/langtools/tools/javac/lvti/SelfRefTest.out +++ b/test/langtools/tools/javac/lvti/SelfRefTest.out @@ -1,4 +1,3 @@ SelfRefTest.java:16:12: compiler.err.cant.infer.local.var.type: x, (compiler.misc.local.self.ref) -SelfRefTest.java:17:53: compiler.err.already.defined: kindname.variable, y, kindname.method, test(boolean) SelfRefTest.java:18:12: compiler.err.cant.infer.local.var.type: z, (compiler.misc.local.self.ref) -3 errors +2 errors diff --git a/test/langtools/tools/javac/patterns/DeconstructionPatternErrors.java b/test/langtools/tools/javac/patterns/DeconstructionPatternErrors.java new file mode 100644 index 00000000000..94745936004 --- /dev/null +++ b/test/langtools/tools/javac/patterns/DeconstructionPatternErrors.java @@ -0,0 +1,40 @@ +/** + * @test /nodynamiccopyright/ + * @summary Verify error reports for erroneous deconstruction patterns are sensible + * @compile/fail/ref=DeconstructionPatternErrors.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=FLOW DeconstructionPatternErrors.java + */ + +import java.util.ArrayList; +import java.util.List; + +public class DeconstructionPatternErrors { + + public static void main(String... args) throws Throwable { + Object p; + p = new P(42); + if (p instanceof P(_)); + if (p instanceof P3(ArrayList<Integer> l)); + if (p instanceof P4(ArrayList<Integer> l)); + if (p instanceof P5(int i)); + if (p instanceof P(String s)); + if (p instanceof P5(P(var v))); + if (p instanceof P2(var v1)); //too few nested patterns + if (p instanceof P2(Runnable v1)); //too few nested patterns + if (p instanceof P(var v1, var v2)); //too many nested patterns + if (p instanceof P(int v1, int v2)); //too many nested patterns + if (p instanceof P(int v1, Unresolvable v2)); //too many nested patterns + if (p instanceof GenRecord<String>(var v)); //incorrect generic type + if (p instanceof P4(GenRecord<String>(var v))); //incorrect generic type + if (p instanceof GenRecord<String>(Integer v)); //inconsistency in types + } + + public record P(int i) { + } + + public record P2(Runnable r1, Runnable r2) {} + public record P3(List<String> l) {} + public record P4(Object o) {} + public record P5(String s) {} + public record GenRecord<T>(T s) {} + +} diff --git a/test/langtools/tools/javac/patterns/DeconstructionPatternErrors.out b/test/langtools/tools/javac/patterns/DeconstructionPatternErrors.out new file mode 100644 index 00000000000..fb6db43447f --- /dev/null +++ b/test/langtools/tools/javac/patterns/DeconstructionPatternErrors.out @@ -0,0 +1,20 @@ +DeconstructionPatternErrors.java:15:28: compiler.err.underscore.as.identifier +DeconstructionPatternErrors.java:15:29: compiler.err.expected: token.identifier +DeconstructionPatternErrors.java:16:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List<java.lang.String>, java.util.ArrayList<java.lang.Integer>) +DeconstructionPatternErrors.java:17:29: compiler.err.instanceof.reifiable.not.safe: java.lang.Object, java.util.ArrayList<java.lang.Integer> +DeconstructionPatternErrors.java:18:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, int) +DeconstructionPatternErrors.java:19:28: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.String) +DeconstructionPatternErrors.java:20:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, DeconstructionPatternErrors.P) +DeconstructionPatternErrors.java:21:26: compiler.err.incorrect.number.of.nested.patterns: java.lang.Runnable,java.lang.Runnable, java.lang.Runnable +DeconstructionPatternErrors.java:22:26: compiler.err.incorrect.number.of.nested.patterns: java.lang.Runnable,java.lang.Runnable, java.lang.Runnable +DeconstructionPatternErrors.java:23:26: compiler.err.incorrect.number.of.nested.patterns: int, int,compiler.misc.type.none +DeconstructionPatternErrors.java:24:26: compiler.err.incorrect.number.of.nested.patterns: int, int,int +DeconstructionPatternErrors.java:25:36: compiler.err.cant.resolve.location: kindname.class, Unresolvable, , , (compiler.misc.location: kindname.class, DeconstructionPatternErrors, null) +DeconstructionPatternErrors.java:25:26: compiler.err.incorrect.number.of.nested.patterns: int, int,Unresolvable +DeconstructionPatternErrors.java:26:13: compiler.err.instanceof.reifiable.not.safe: java.lang.Object, DeconstructionPatternErrors.GenRecord<java.lang.String> +DeconstructionPatternErrors.java:27:29: compiler.err.instanceof.reifiable.not.safe: java.lang.Object, DeconstructionPatternErrors.GenRecord<java.lang.String> +DeconstructionPatternErrors.java:28:44: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer) +DeconstructionPatternErrors.java:28:13: compiler.err.instanceof.reifiable.not.safe: java.lang.Object, DeconstructionPatternErrors.GenRecord<java.lang.String> +- compiler.note.preview.filename: DeconstructionPatternErrors.java +- compiler.note.preview.recompile +17 errors diff --git a/test/langtools/tools/javac/patterns/PrettyTest.java b/test/langtools/tools/javac/patterns/PrettyTest.java new file mode 100644 index 00000000000..4714e8550b7 --- /dev/null +++ b/test/langtools/tools/javac/patterns/PrettyTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 behavior of Pretty + * @modules jdk.compiler + * @compile --enable-preview -source ${jdk.version} PrettyTest.java + * @run main/othervm --enable-preview PrettyTest + */ + +import java.io.IOException; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; +import java.util.List; + +import javax.tools.*; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.JavacTask; + +public class PrettyTest { + + public static void main(String[] args) throws Exception { + new PrettyTest().run(); + } + + void run() throws Exception { + String code = "class Test {\n" + + " boolean t(Object o) {\n" + + " boolean b;\n" + + " b = o instanceof String s;\n" + + " b = o instanceof R(String s);\n" + + " b = o instanceof R(var s);\n" + + " b = o instanceof R2(R(var s), String t);\n" + + " b = o instanceof R2(R(var s), var t);\n" + + " }\n" + + " record R(String s) {}\n" + + " record R2(R r, String s) {}\n" + + "}\n"; + String pretty = parse(code).toString(); + String expected = """ + \n\ + class Test { + \n\ + boolean t(Object o) { + boolean b; + b = o instanceof String s; + b = o instanceof R(String s); + b = o instanceof R(/*missing*/ s); + b = o instanceof R2(R(/*missing*/ s), String t); + b = o instanceof R2(R(/*missing*/ s), /*missing*/ t); + } + \n\ + class R { + private final String s; + } + \n\ + class R2 { + private final R r; + private final String s; + } + }"""; + if (!expected.equals(pretty)) { + throw new AssertionError("Actual prettified source: " + pretty); + } + } + + private CompilationUnitTree parse(String code) throws IOException { + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + assert tool != null; + DiagnosticListener<JavaFileObject> noErrors = d -> {}; + + StringWriter out = new StringWriter(); + JavacTask ct = (JavacTask) tool.getTask(out, null, noErrors, + List.of("--enable-preview", "-source", Integer.toString(Runtime.version().feature())), null, + Arrays.asList(new MyFileObject(code))); + return ct.parse().iterator().next(); + } + + static class MyFileObject extends SimpleJavaFileObject { + private String text; + + public MyFileObject(String text) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.text = text; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return text; + } + } +} diff --git a/test/langtools/tools/javac/patterns/SimpleDeconstructionPattern.java b/test/langtools/tools/javac/patterns/SimpleDeconstructionPattern.java new file mode 100644 index 00000000000..f295cfa7ca3 --- /dev/null +++ b/test/langtools/tools/javac/patterns/SimpleDeconstructionPattern.java @@ -0,0 +1,246 @@ +/** + * @test + * @compile/fail/ref=SimpleDeconstructionPatternNoPreview.out -XDrawDiagnostics SimpleDeconstructionPattern.java + * @compile --enable-preview -source ${jdk.version} SimpleDeconstructionPattern.java + * @run main/othervm --enable-preview SimpleDeconstructionPattern + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class SimpleDeconstructionPattern { + + public static void main(String... args) throws Throwable { +// if (!test1(new P(42))) { +// throw new IllegalStateException(); +// } +// if (test1(new P(41))) { +// throw new IllegalStateException(); +// } + if (!test2(new P(42))) { + throw new IllegalStateException(); + } + if (test2(new P(41))) { + throw new IllegalStateException(); + } + if (!test2a(new P(42))) { + throw new IllegalStateException(); + } + if (test2a(new P(41))) { + throw new IllegalStateException(); + } +// if (!test3(new P2(new P(42), ""))) { +// throw new IllegalStateException(); +// } +// if (test3(new P2(new P(41), ""))) { +// throw new IllegalStateException(); +// } +// if (test3(new P2(new P(42), "a"))) { +// throw new IllegalStateException(); +// } + if (!test4(new P2(new P(42), ""))) { + throw new IllegalStateException(); + } + if (test4(new P2(new P(41), ""))) { + throw new IllegalStateException(); + } + if (test4(new P2(new P(42), "a"))) { + throw new IllegalStateException(); + } + if (!test5(new P(42))) { + throw new IllegalStateException(); + } + if (test5(new P(41))) { + throw new IllegalStateException(); + } +// if (!test6(new P(42))) { +// throw new IllegalStateException(); +// } +// if (!test6(new P(41))) { +// throw new IllegalStateException(); +// } +// if (!((new BaseUse(new BaseSubclass(0))) instanceof BaseUse(BaseSubclass(0)))) { +// throw new IllegalStateException(); +// } + if (!test7(new P3(""))) { + throw new IllegalStateException(); + } + if (test7(new P3("a"))) { + throw new IllegalStateException(); + } + if (!test7a(new P3(""))) { + throw new IllegalStateException(); + } + if (test7a(new P3("a"))) { + throw new IllegalStateException(); + } + if (test8(new P4(""))) { + throw new IllegalStateException(); + } + if (!test8(new P4(new P3("")))) { + throw new IllegalStateException(); + } + if (!test8a(new P4(new P3("")))) { + throw new IllegalStateException(); + } + if (test8(new P4(new P3("a")))) { + throw new IllegalStateException(); + } + if (test8a(new P4(new P3("a")))) { + throw new IllegalStateException(); + } + if (!test9(new P5(new ArrayList<String>(Arrays.asList(""))))) { + throw new IllegalStateException(); + } + if (test9(new P5(new LinkedList<String>(Arrays.asList(""))))) { + throw new IllegalStateException(); + } + if (testA(new P6(null))) { + throw new IllegalStateException(); + } + if (testA(new P6(new P3(null)))) { + throw new IllegalStateException(); + } + if (testB(new P6(null))) { + throw new IllegalStateException(); + } + if (testB(new P6(new P3(null)))) { + throw new IllegalStateException(); + } + if (testC(new P6(null))) { + throw new IllegalStateException(); + } + if (testC(new P6(new P3(null)))) { + throw new IllegalStateException(); + } + if (!testC(new P6(new P3("")))) { + throw new IllegalStateException(); + } + if (!testGen1(new GenRecord1<>(1L, ""))) { + throw new IllegalStateException(); + } + if (testGen1(new GenRecord1<>(1L, "a"))) { + throw new IllegalStateException(); + } + if (testGen2(new GenRecord1<>(3L, ""))) { + throw new IllegalStateException(); + } + if (!testGen2(new GenRecord1<>(3, ""))) { + throw new IllegalStateException(); + } + if (testGen3(new GenRecord1<>(3L, ""))) { + throw new IllegalStateException(); + } + if (!testGen3(new GenRecord1<>(3, ""))) { + throw new IllegalStateException(); + } + if (!testGen3(new GenRecord1<>(3, ""))) { + throw new IllegalStateException(); + } + } + +// private static boolean test1(Object o) throws Throwable { +// return o instanceof P(42); +// } +// + private static void exp(Object o) throws Throwable { + if (o instanceof P(var i)) { + System.err.println("i=" + i); + } + } + + private static boolean test2(Object o) throws Throwable { + return o instanceof P(var i) && i == 42; + } + + private static boolean test2a(Object o) throws Throwable { + return o instanceof P(int i) && i == 42; + } + +// private static boolean test3(Object o) throws Throwable { +// return o instanceof P2(P(42), ""); +// } +// + private static boolean test4(Object o) throws Throwable { + return o instanceof P2(P(var i), var s) && i == 42 && "".equals(s); + } + + private static boolean test5(Object o) throws Throwable { + return o instanceof P(var i) && i == 42; + } + +// private static boolean test6(Object o) throws Throwable { +// return o instanceof P(_); +// } + + private static boolean test7(Object o) throws Throwable { + return o instanceof P3(var s) && "".equals(s); + } + + private static boolean test7a(Object o) throws Throwable { + return o instanceof P3(String s) && "".equals(s); + } + + private static boolean test8(Object o) throws Throwable { + return o instanceof P4(P3(var s)) && "".equals(s); + } + + private static boolean test8a(Object o) throws Throwable { + return o instanceof P4(P3(String s)) && "".equals(s); + } + + private static boolean test9(Object o) throws Throwable { + return o instanceof P5(ArrayList<String> l) && !l.isEmpty(); + } + + private static boolean testA(Object o) throws Throwable { + return o instanceof P6(P3(var s)); + } + + private static boolean testB(Object o) throws Throwable { + return o instanceof P6(P3(String s)); + } + + private static boolean testC(Object o) throws Throwable { + return o instanceof P6(P3(String s)) && s.isEmpty(); + } + + private static boolean testGen1(Object o) throws Throwable { + return o instanceof GenRecord1(var i, var s) && s.length() == 0; + } + + private static boolean testGen2(Object o) throws Throwable { + return o instanceof GenRecord1(Integer i, var s) && i.intValue() == 3 && s.length() == 0; + } + + private static boolean testGen3(Object o) throws Throwable { + return o instanceof GenRecord1<?, ?>(Integer i, var s) && i.intValue() == 3 && s.length() == 0; + } + + private static boolean testGen4(GenBase<Integer, String> o) throws Throwable { + return o instanceof GenRecord1<Integer, String>(var i, var s) && i.intValue() == 3 && s.length() == 0; + } + + public record P(int i) { + } + + public record P2(P p, String s) { + } + + public record P3(String s) { + } + + public record P4(Object o) {} + + public record P5(List<String> l) {} + public record P6(P3 p) {} + + public interface Base {} + public record BaseUse(Base b) {} + public record BaseSubclass(int i) implements Base {} + + public interface GenBase<T1, T2 extends CharSequence> {} + public record GenRecord1<T1, T2 extends CharSequence> (T1 i, T2 s) implements GenBase<T1, T2> {} +} diff --git a/test/langtools/tools/javac/patterns/SimpleDeconstructionPatternNoPreview.out b/test/langtools/tools/javac/patterns/SimpleDeconstructionPatternNoPreview.out new file mode 100644 index 00000000000..b08eb1f0fde --- /dev/null +++ b/test/langtools/tools/javac/patterns/SimpleDeconstructionPatternNoPreview.out @@ -0,0 +1,17 @@ +SimpleDeconstructionPattern.java:149:27: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.deconstruction.patterns) +SimpleDeconstructionPattern.java:226:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:229:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:232:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:235:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:237:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:238:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:241:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:242:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:242:38: compiler.err.expected: ';' +SimpleDeconstructionPattern.java:245:12: compiler.warn.restricted.type.not.allowed.preview: record, 14 +SimpleDeconstructionPattern.java:245:29: compiler.err.expected: ';' +SimpleDeconstructionPattern.java:245:59: compiler.err.illegal.start.of.type +SimpleDeconstructionPattern.java:245:71: compiler.err.expected: ';' +SimpleDeconstructionPattern.java:245:99: compiler.err.illegal.start.of.type +6 errors +9 warnings diff --git a/test/langtools/tools/javac/sealed/SealedCompilationTests.java b/test/langtools/tools/javac/sealed/SealedCompilationTests.java index 5313d5a1275..3671046b05a 100644 --- a/test/langtools/tools/javac/sealed/SealedCompilationTests.java +++ b/test/langtools/tools/javac/sealed/SealedCompilationTests.java @@ -956,4 +956,15 @@ sealed static class Super permits Outer.Sub {} assertOK(s); } } + + public void testDoNotAllowSealedAnnotation() { + for (String s : List.of( + """ + sealed @interface A {} + non-sealed interface I extends A {} + """ + )) { + assertFail("compiler.err.expected4", s); + } + } } diff --git a/test/lib/jdk/test/lib/SigTestUtil.java b/test/lib/jdk/test/lib/SigTestUtil.java index f6775cda37d..b04f2215f8a 100644 --- a/test/lib/jdk/test/lib/SigTestUtil.java +++ b/test/lib/jdk/test/lib/SigTestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,10 +54,14 @@ public String toString() { // collection of all supported digest algorithms // note that the entries are ordered by required key sizes private static final String[] DIGEST_ALGS = { + "SHA3-512", "SHA-512", + "SHA3-384", "SHA-384", + "SHA3-256", "SHA-256", "SHA-512/256", + "SHA3-224", "SHA-224", "SHA-512/224", "SHA-1", @@ -66,14 +70,14 @@ public String toString() { // indice for message digest algorithms lookup // may need to be adjusted if new algorithms are added - private static final int PKCS1_5_INDEX_768 = 0; - private static final int PKCS1_5_INDEX_512 = 2; + private static final int PKCS1_5_INDEX_768 = 0; // 512, 384-bit digests + private static final int PKCS1_5_INDEX_512 = 4; // 256-bit digests private static final int PKCS1_5_INDEX_END = DIGEST_ALGS.length; - private static final int PSS_INDEX_2048 = 0; - private static final int PSS_INDEX_1024 = 1; - private static final int PSS_INDEX_768 = 2; - private static final int PSS_INDEX_512 = 4; - private static final int PSS_INDEX_END = 7; + private static final int PSS_INDEX_2048 = 0; // 512-bit digests + private static final int PSS_INDEX_1024 = 2; // 384-bit digests + private static final int PSS_INDEX_768 = 4; // 256-bit digests + private static final int PSS_INDEX_512 = 7; // 224-bit digests + private static final int PSS_INDEX_END = DIGEST_ALGS.length - 2; public static Iterable<String> getDigestAlgorithms(SignatureType type, int keysize) throws RuntimeException { @@ -135,9 +139,8 @@ public static String generateSigAlg(SignatureType type, String mdAlg) throws RuntimeException { switch (type) { case RSA: - int idx = mdAlg.indexOf("-"); - if (idx != -1) { - mdAlg = mdAlg.substring(0, idx) + mdAlg.substring(idx+1); + if (mdAlg.startsWith("SHA-")) { + mdAlg = mdAlg.substring(0, 3) + mdAlg.substring(4); } return mdAlg + "with" + type.toString(); case RSASSA_PSS: diff --git a/test/micro/org/openjdk/bench/java/net/ThreadLocalParseUtil.java b/test/micro/org/openjdk/bench/java/net/ThreadLocalParseUtil.java new file mode 100644 index 00000000000..1bdcefbef7d --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/ThreadLocalParseUtil.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.net.URI; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +import static java.lang.invoke.MethodType.methodType; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Fork(value = 1, jvmArgsAppend = "--add-exports=java.base/sun.net.www=ALL-UNNAMED") +public class ThreadLocalParseUtil { + + private static final MethodHandle MH_DECODE; + private static final MethodHandle MH_TO_URI; + + static { + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + Class<?> c = Class.forName("sun.net.www.ParseUtil"); + MH_DECODE = lookup.findStatic(c, "decode", methodType(String.class, String.class)); + MH_TO_URI = lookup.findStatic(c, "toURI", methodType(URI.class, URL.class)); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) { + throw new ExceptionInInitializerError(e); + } + } + + @Benchmark + public String decodeTest() throws Throwable { + return (String) MH_DECODE.invokeExact("/xyz/\u00A0\u00A0"); + } + + @Benchmark + public URI appendEncodedTest() throws Throwable { + URL url = new URL("https://example.com/xyz/abc/def?query=#30"); + return (URI) MH_TO_URI.invokeExact(url); + } +}